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