Home | History | Annotate | Download | only in preference
      1 /*
      2  * Copyright 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.preference;
     18 
     19 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
     20 
     21 import android.content.Context;
     22 import android.util.AttributeSet;
     23 import android.view.View;
     24 import android.widget.AdapterView;
     25 import android.widget.AdapterView.OnItemSelectedListener;
     26 import android.widget.ArrayAdapter;
     27 import android.widget.Spinner;
     28 
     29 import androidx.annotation.NonNull;
     30 import androidx.annotation.RestrictTo;
     31 
     32 /**
     33  * A version of {@link ListPreference} that presents the options in a
     34  * drop down menu rather than a dialog.
     35  */
     36 public class DropDownPreference extends ListPreference {
     37 
     38     private final Context mContext;
     39     private final ArrayAdapter mAdapter;
     40 
     41     private Spinner mSpinner;
     42 
     43     public DropDownPreference(Context context) {
     44         this(context, null);
     45     }
     46 
     47     public DropDownPreference(Context context, AttributeSet attrs) {
     48         this(context, attrs, R.attr.dropdownPreferenceStyle);
     49     }
     50 
     51     public DropDownPreference(Context context, AttributeSet attrs, int defStyle) {
     52         this(context, attrs, defStyle, 0);
     53     }
     54 
     55     public DropDownPreference(Context context, AttributeSet attrs, int defStyleAttr,
     56             int defStyleRes) {
     57         super(context, attrs, defStyleAttr, defStyleRes);
     58         mContext = context;
     59         mAdapter = createAdapter();
     60 
     61         updateEntries();
     62     }
     63 
     64     @Override
     65     protected void onClick() {
     66         mSpinner.performClick();
     67     }
     68 
     69     @Override
     70     public void setEntries(@NonNull CharSequence[] entries) {
     71         super.setEntries(entries);
     72         updateEntries();
     73     }
     74 
     75 
     76     /**
     77      * By default, this class uses a simple {@link android.widget.ArrayAdapter}. But if you need
     78      * a more complicated {@link android.widget.ArrayAdapter}, this method can be overridden to
     79      * create a custom one.
     80      * <p> Note: This method is called from the constructor. So, overridden methods will get called
     81      * before any subclass initialization.
     82      *
     83      * @return The custom {@link android.widget.ArrayAdapter} that needs to be used with this class.
     84      */
     85     protected ArrayAdapter createAdapter() {
     86         return new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_dropdown_item);
     87     }
     88 
     89     private void updateEntries() {
     90         mAdapter.clear();
     91         if (getEntries() != null) {
     92             for (CharSequence c : getEntries()) {
     93                 mAdapter.add(c.toString());
     94             }
     95         }
     96     }
     97 
     98     @Override
     99     public void setValueIndex(int index) {
    100         setValue(getEntryValues()[index].toString());
    101     }
    102 
    103     /**
    104      * @hide
    105      */
    106     @RestrictTo(LIBRARY_GROUP)
    107     public int findSpinnerIndexOfValue(String value) {
    108         CharSequence[] entryValues = getEntryValues();
    109         if (value != null && entryValues != null) {
    110             for (int i = entryValues.length - 1; i >= 0; i--) {
    111                 if (entryValues[i].equals(value)) {
    112                     return i;
    113                 }
    114             }
    115         }
    116         return Spinner.INVALID_POSITION;
    117     }
    118 
    119     @Override
    120     protected void notifyChanged() {
    121         super.notifyChanged();
    122         mAdapter.notifyDataSetChanged();
    123     }
    124 
    125     @Override
    126     public void onBindViewHolder(PreferenceViewHolder view) {
    127         mSpinner = (Spinner) view.itemView.findViewById(R.id.spinner);
    128         mSpinner.setAdapter(mAdapter);
    129         mSpinner.setOnItemSelectedListener(mItemSelectedListener);
    130         mSpinner.setSelection(findSpinnerIndexOfValue(getValue()));
    131         super.onBindViewHolder(view);
    132     }
    133 
    134     private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
    135         @Override
    136         public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
    137             if (position >= 0) {
    138                 String value = getEntryValues()[position].toString();
    139                 if (!value.equals(getValue()) && callChangeListener(value)) {
    140                     setValue(value);
    141                 }
    142             }
    143         }
    144 
    145         @Override
    146         public void onNothingSelected(AdapterView<?> parent) {
    147             // noop
    148         }
    149     };
    150 }
    151 
    152