Home | History | Annotate | Download | only in widget
      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 package com.android.settings.widget;
     17 
     18 import android.app.AlertDialog;
     19 import android.content.res.TypedArray;
     20 import android.os.Bundle;
     21 import android.support.annotation.VisibleForTesting;
     22 import android.support.v14.preference.PreferenceDialogFragment;
     23 import android.support.v7.preference.ListPreference;
     24 import android.widget.ArrayAdapter;
     25 import com.android.settingslib.core.instrumentation.Instrumentable;
     26 
     27 import java.util.ArrayList;
     28 
     29 /**
     30  * {@link PreferenceDialogFragment} that updates the available options
     31  * when {@code onListPreferenceUpdated} is called."
     32  */
     33 public class UpdatableListPreferenceDialogFragment extends PreferenceDialogFragment implements
     34         Instrumentable {
     35 
     36     private static final String SAVE_STATE_INDEX = "UpdatableListPreferenceDialogFragment.index";
     37     private static final String SAVE_STATE_ENTRIES =
     38             "UpdatableListPreferenceDialogFragment.entries";
     39     private static final String SAVE_STATE_ENTRY_VALUES =
     40             "UpdatableListPreferenceDialogFragment.entryValues";
     41     private static final String METRICS_CATEGORY_KEY = "metrics_category_key";
     42     private ArrayAdapter mAdapter;
     43     private int mClickedDialogEntryIndex;
     44     private ArrayList<CharSequence> mEntries;
     45     private CharSequence[] mEntryValues;
     46     private int mMetricsCategory = Instrumentable.METRICS_CATEGORY_UNKNOWN;
     47 
     48     public static UpdatableListPreferenceDialogFragment newInstance(
     49             String key, int metricsCategory) {
     50         UpdatableListPreferenceDialogFragment fragment =
     51                 new UpdatableListPreferenceDialogFragment();
     52         Bundle args = new Bundle(1);
     53         args.putString(ARG_KEY, key);
     54         args.putInt(METRICS_CATEGORY_KEY, metricsCategory);
     55         fragment.setArguments(args);
     56         return fragment;
     57     }
     58 
     59     public void onCreate(Bundle savedInstanceState) {
     60         super.onCreate(savedInstanceState);
     61         final Bundle bundle = getArguments();
     62         mMetricsCategory =
     63                 bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
     64         if (savedInstanceState == null) {
     65             mEntries = new ArrayList<>();
     66             setPreferenceData(getListPreference());
     67         } else {
     68             mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
     69             mEntries = savedInstanceState.getCharSequenceArrayList(SAVE_STATE_ENTRIES);
     70             mEntryValues =
     71                     savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
     72         }
     73     }
     74 
     75     @Override
     76     public void onSaveInstanceState(Bundle outState) {
     77         super.onSaveInstanceState(outState);
     78         outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
     79         outState.putCharSequenceArrayList(SAVE_STATE_ENTRIES, mEntries);
     80         outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
     81     }
     82 
     83     @Override
     84     public void onDialogClosed(boolean positiveResult) {
     85         final ListPreference preference = getListPreference();
     86         if (positiveResult && mClickedDialogEntryIndex >= 0) {
     87             final String value = mEntryValues[mClickedDialogEntryIndex].toString();
     88             if (preference.callChangeListener(value)) {
     89                 preference.setValue(value);
     90             }
     91         }
     92     }
     93 
     94     @VisibleForTesting
     95     void setAdapter(ArrayAdapter adapter) {
     96         mAdapter = adapter;
     97     }
     98 
     99     @VisibleForTesting
    100     void setEntries(ArrayList<CharSequence> entries) {
    101         mEntries = entries;
    102     }
    103 
    104     @VisibleForTesting
    105     ArrayAdapter getAdapter() {
    106         return mAdapter;
    107     }
    108 
    109     @VisibleForTesting
    110     void setMetricsCategory(Bundle bundle) {
    111         mMetricsCategory =
    112                 bundle.getInt(METRICS_CATEGORY_KEY, Instrumentable.METRICS_CATEGORY_UNKNOWN);
    113     }
    114 
    115     @Override
    116     protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
    117         super.onPrepareDialogBuilder(builder);
    118         final TypedArray a = getContext().obtainStyledAttributes(
    119                 null,
    120                 com.android.internal.R.styleable.AlertDialog,
    121                 com.android.internal.R.attr.alertDialogStyle, 0);
    122 
    123         mAdapter = new ArrayAdapter<>(
    124                 getContext(),
    125                 a.getResourceId(
    126                         com.android.internal.R.styleable.AlertDialog_singleChoiceItemLayout,
    127                         com.android.internal.R.layout.select_dialog_singlechoice),
    128                 mEntries);
    129 
    130         builder.setSingleChoiceItems(mAdapter, mClickedDialogEntryIndex,
    131                 (dialog, which) -> {
    132                     mClickedDialogEntryIndex = which;
    133                     onClick(dialog, -1);
    134                     dialog.dismiss();
    135                 });
    136         builder.setPositiveButton(null, null);
    137         a.recycle();
    138     }
    139 
    140     @Override
    141     public int getMetricsCategory() {
    142         return mMetricsCategory;
    143     }
    144 
    145     private ListPreference getListPreference() {
    146         return (ListPreference) getPreference();
    147     }
    148 
    149     private void setPreferenceData(ListPreference preference) {
    150         mEntries.clear();
    151         mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
    152         for (CharSequence entry : preference.getEntries()) {
    153             mEntries.add(entry);
    154         }
    155         mEntryValues = preference.getEntryValues();
    156     }
    157 
    158     public void onListPreferenceUpdated(ListPreference preference) {
    159         if (mAdapter != null) {
    160             setPreferenceData(preference);
    161             mAdapter.notifyDataSetChanged();
    162         }
    163     }
    164 }
    165