15c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk/* 25c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * Copyright (C) 2015 The Android Open Source Project 35c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * 45c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); 55c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * you may not use this file except in compliance with the License. 65c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * You may obtain a copy of the License at 75c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * 85c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 95c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * 105c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * Unless required by applicable law or agreed to in writing, software 115c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * distributed under the License is distributed on an "AS IS" BASIS, 125c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * See the License for the specific language governing permissions and 145c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * limitations under the License. 155c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk */ 165c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 175c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkpackage android.support.v7.preference; 185c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 198e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 208e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas 215c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.content.Context; 225c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.support.annotation.NonNull; 23c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo; 245c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.util.AttributeSet; 255c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.view.View; 265c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.widget.AdapterView; 275c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.widget.AdapterView.OnItemSelectedListener; 285c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.widget.ArrayAdapter; 295c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkimport android.widget.Spinner; 305c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 313a289c5ac0c61d2156879cebccff0aba479288eeJason Monk/** 323a289c5ac0c61d2156879cebccff0aba479288eeJason Monk * A version of {@link ListPreference} that presents the options in a 333a289c5ac0c61d2156879cebccff0aba479288eeJason Monk * drop down menu rather than a dialog. 343a289c5ac0c61d2156879cebccff0aba479288eeJason Monk */ 355c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monkpublic class DropDownPreference extends ListPreference { 365c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 375c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk private final Context mContext; 38f82cdb0326f2cb78809fe0c536c5fbb527b7ae00Filip Pavlis private final ArrayAdapter mAdapter; 395c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 405c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk private Spinner mSpinner; 415c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 425c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public DropDownPreference(Context context) { 435c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk this(context, null); 445c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 455c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 465c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public DropDownPreference(Context context, AttributeSet attrs) { 475c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk this(context, attrs, R.attr.dropdownPreferenceStyle); 485c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 495c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 505c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public DropDownPreference(Context context, AttributeSet attrs, int defStyle) { 515c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk this(context, attrs, defStyle, 0); 525c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 535c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 545c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public DropDownPreference(Context context, AttributeSet attrs, int defStyleAttr, 555c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk int defStyleRes) { 565c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk super(context, attrs, defStyleAttr, defStyleRes); 575c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mContext = context; 58d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka mAdapter = createAdapter(); 595c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 605c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk updateEntries(); 615c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 625c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 635c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk @Override 645c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk protected void onClick() { 655c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mSpinner.performClick(); 665c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 675c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 685c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk @Override 695c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public void setEntries(@NonNull CharSequence[] entries) { 705c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk super.setEntries(entries); 715c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk updateEntries(); 725c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 735c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 74d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka 75d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka /** 76d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka * By default, this class uses a simple {@link android.widget.ArrayAdapter}. But if you need 77c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas * a more complicated {@link android.widget.ArrayAdapter}, this method can be overridden to 78d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka * create a custom one. 79c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas * <p> Note: This method is called from the constructor. So, overridden methods will get called 80d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka * before any subclass initialization. 81d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka * 82d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka * @return The custom {@link android.widget.ArrayAdapter} that needs to be used with this class. 83d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka */ 84d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka protected ArrayAdapter createAdapter() { 85d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka return new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_dropdown_item); 86d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka } 87d252c4e5c825e86c2f8ceeb68a41e9ead2cc95d4Sudheer Shanka 885c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk private void updateEntries() { 895c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mAdapter.clear(); 905c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk if (getEntries() != null) { 915c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk for (CharSequence c : getEntries()) { 925c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mAdapter.add(c.toString()); 935c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 945c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 955c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 965c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 97dc8e099ed130434c0238f558277c5bcb6a533121Aurimas Liutikas @Override 985c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public void setValueIndex(int index) { 995c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk setValue(getEntryValues()[index].toString()); 1005c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1015c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 1025c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk /** 1035c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk * @hide 1045c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk */ 1058e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas @RestrictTo(LIBRARY_GROUP) 1065c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public int findSpinnerIndexOfValue(String value) { 1075c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk CharSequence[] entryValues = getEntryValues(); 1085c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk if (value != null && entryValues != null) { 1095c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk for (int i = entryValues.length - 1; i >= 0; i--) { 1105c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk if (entryValues[i].equals(value)) { 1115c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk return i; 1125c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1135c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1145c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1155c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk return Spinner.INVALID_POSITION; 1165c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1175c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 1185c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk @Override 1195c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk protected void notifyChanged() { 1205c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk super.notifyChanged(); 1215c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mAdapter.notifyDataSetChanged(); 1225c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1235c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 1245c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk @Override 1255c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public void onBindViewHolder(PreferenceViewHolder view) { 1265c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mSpinner = (Spinner) view.itemView.findViewById(R.id.spinner); 1275c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mSpinner.setAdapter(mAdapter); 1285c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mSpinner.setOnItemSelectedListener(mItemSelectedListener); 1295c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk mSpinner.setSelection(findSpinnerIndexOfValue(getValue())); 1305c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk super.onBindViewHolder(view); 1315c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1325c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 1335c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() { 1345c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk @Override 1355c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public void onItemSelected(AdapterView<?> parent, View v, int position, long id) { 1365c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk if (position >= 0) { 1375c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk String value = getEntryValues()[position].toString(); 1385c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk if (!value.equals(getValue()) && callChangeListener(value)) { 1395c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk setValue(value); 1405c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1415c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1425c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1435c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 1445c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk @Override 1455c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk public void onNothingSelected(AdapterView<?> parent) { 1465c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk // noop 1475c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk } 1485c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk }; 1495c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk} 1505c87ca2b30d38c06342ec17b3cfc1296c2295ff6Jason Monk 151