/* * Copyright (c) 2015 Ha Duy Trung * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.github.hidroh.materialistic.preference; import android.content.Context; import android.content.res.TypedArray; import android.database.DataSetObserver; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceViewHolder; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Spinner; import android.widget.SpinnerAdapter; import io.github.hidroh.materialistic.R; import io.github.hidroh.materialistic.annotation.Synthetic; /** * {@link Preference} with spinner as custom widget. * Entries, entry values and entry layouts should be provided via arrays. * Preference value will be persisted as string. */ public abstract class SpinnerPreference extends Preference { @Synthetic String[] mEntries = new String[0]; @Synthetic String[] mEntryValues = new String[0]; @Synthetic int mSelection = 0; @SuppressWarnings("unused") public SpinnerPreference(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SpinnerPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setWidgetLayoutResource(R.layout.preference_spinner); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SpinnerPreference); int entriesResId = ta.getResourceId(R.styleable.SpinnerPreference_entries, 0); if (entriesResId != 0) { mEntries = context.getResources().getStringArray(entriesResId); } int valuesResId = ta.getResourceId(R.styleable.SpinnerPreference_entryValues, 0); if (valuesResId != 0) { mEntryValues = context.getResources().getStringArray(valuesResId); } ta.recycle(); } @Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getString(index); } @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { super.onSetInitialValue(restorePersistedValue, defaultValue); String value = restorePersistedValue ? getPersistedString(null) : (String) defaultValue; for (int i = 0; i < mEntryValues.length; i++) { if (TextUtils.equals(mEntryValues[i], value)) { mSelection = i; break; } } } @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); final Spinner spinner = (Spinner) holder.findViewById(R.id.spinner); holder.itemView.setOnClickListener(v -> spinner.performClick()); spinner.setAdapter(new SpinnerAdapter() { @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = createDropDownView(position, parent); } bindDropDownView(position, convertView); return convertView; } @Override public void registerDataSetObserver(DataSetObserver observer) { // no op } @Override public void unregisterDataSetObserver(DataSetObserver observer) { // no op } @Override public int getCount() { return mEntries.length; } @Override public Object getItem(int position) { return null; // not applicable } @Override public long getItemId(int position) { return position; } @Override public boolean hasStableIds() { return true; } @Override public View getView(int position, View convertView, ViewGroup parent) { return getDropDownView(position, convertView, parent); } @Override public int getItemViewType(int position) { return 0; } @Override public int getViewTypeCount() { return 1; } @Override public boolean isEmpty() { return false; } }); spinner.setSelection(mSelection); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { mSelection = position; persistString(mEntryValues[position]); } @Override public void onNothingSelected(AdapterView<?> parent) { // no op } }); } /** * Create dropdown view for item at given position * @param position item position * @param parent parent view * @return created view */ protected abstract View createDropDownView(int position, ViewGroup parent); /** * Customize dropdown view for given spinner item * @param position item position * @param view item view */ protected abstract void bindDropDownView(int position, View view); }