Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2011 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 com.android.settings;
     18 
     19 import android.content.Context;
     20 import android.content.res.TypedArray;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 import android.support.v7.preference.Preference;
     24 import android.support.v7.preference.PreferenceViewHolder;
     25 import android.util.AttributeSet;
     26 import android.view.KeyEvent;
     27 import android.view.View;
     28 import android.widget.SeekBar;
     29 import android.widget.SeekBar.OnSeekBarChangeListener;
     30 
     31 import com.android.settingslib.RestrictedPreference;
     32 
     33 /**
     34  * Based on android.preference.SeekBarPreference, but uses support preference as base.
     35  */
     36 public class SeekBarPreference extends RestrictedPreference
     37         implements OnSeekBarChangeListener, View.OnKeyListener {
     38 
     39     private int mProgress;
     40     private int mMax;
     41     private boolean mTrackingTouch;
     42 
     43     public SeekBarPreference(
     44             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
     45         super(context, attrs, defStyleAttr, defStyleRes);
     46 
     47         TypedArray a = context.obtainStyledAttributes(
     48                 attrs, com.android.internal.R.styleable.ProgressBar, defStyleAttr, defStyleRes);
     49         setMax(a.getInt(com.android.internal.R.styleable.ProgressBar_max, mMax));
     50         a.recycle();
     51 
     52         a = context.obtainStyledAttributes(attrs,
     53                 com.android.internal.R.styleable.SeekBarPreference, defStyleAttr, defStyleRes);
     54         final int layoutResId = a.getResourceId(
     55                 com.android.internal.R.styleable.SeekBarPreference_layout,
     56                 com.android.internal.R.layout.preference_widget_seekbar);
     57         a.recycle();
     58 
     59         setLayoutResource(layoutResId);
     60     }
     61 
     62     public SeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
     63         this(context, attrs, defStyleAttr, 0);
     64     }
     65 
     66     public SeekBarPreference(Context context, AttributeSet attrs) {
     67         this(context, attrs, com.android.internal.R.attr.seekBarPreferenceStyle);
     68     }
     69 
     70     public SeekBarPreference(Context context) {
     71         this(context, null);
     72     }
     73 
     74     @Override
     75     public void onBindViewHolder(PreferenceViewHolder view) {
     76         super.onBindViewHolder(view);
     77         view.itemView.setOnKeyListener(this);
     78         SeekBar seekBar = (SeekBar) view.findViewById(
     79                 com.android.internal.R.id.seekbar);
     80         seekBar.setOnSeekBarChangeListener(this);
     81         seekBar.setMax(mMax);
     82         seekBar.setProgress(mProgress);
     83         seekBar.setEnabled(isEnabled());
     84     }
     85 
     86     @Override
     87     public CharSequence getSummary() {
     88         return null;
     89     }
     90 
     91     @Override
     92     protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
     93         setProgress(restoreValue ? getPersistedInt(mProgress)
     94                 : (Integer) defaultValue);
     95     }
     96 
     97     @Override
     98     protected Object onGetDefaultValue(TypedArray a, int index) {
     99         return a.getInt(index, 0);
    100     }
    101 
    102     @Override
    103     public boolean onKey(View v, int keyCode, KeyEvent event) {
    104         if (event.getAction() != KeyEvent.ACTION_DOWN) {
    105             return false;
    106         }
    107 
    108         SeekBar seekBar = (SeekBar) v.findViewById(com.android.internal.R.id.seekbar);
    109         if (seekBar == null) {
    110             return false;
    111         }
    112         return seekBar.onKeyDown(keyCode, event);
    113     }
    114 
    115     public void setMax(int max) {
    116         if (max != mMax) {
    117             mMax = max;
    118             notifyChanged();
    119         }
    120     }
    121 
    122     public void setProgress(int progress) {
    123         setProgress(progress, true);
    124     }
    125 
    126     private void setProgress(int progress, boolean notifyChanged) {
    127         if (progress > mMax) {
    128             progress = mMax;
    129         }
    130         if (progress < 0) {
    131             progress = 0;
    132         }
    133         if (progress != mProgress) {
    134             mProgress = progress;
    135             persistInt(progress);
    136             if (notifyChanged) {
    137                 notifyChanged();
    138             }
    139         }
    140     }
    141 
    142     public int getProgress() {
    143         return mProgress;
    144     }
    145 
    146     /**
    147      * Persist the seekBar's progress value if callChangeListener
    148      * returns true, otherwise set the seekBar's progress to the stored value
    149      */
    150     void syncProgress(SeekBar seekBar) {
    151         int progress = seekBar.getProgress();
    152         if (progress != mProgress) {
    153             if (callChangeListener(progress)) {
    154                 setProgress(progress, false);
    155             } else {
    156                 seekBar.setProgress(mProgress);
    157             }
    158         }
    159     }
    160 
    161     @Override
    162     public void onProgressChanged(
    163             SeekBar seekBar, int progress, boolean fromUser) {
    164         if (fromUser && !mTrackingTouch) {
    165             syncProgress(seekBar);
    166         }
    167     }
    168 
    169     @Override
    170     public void onStartTrackingTouch(SeekBar seekBar) {
    171         mTrackingTouch = true;
    172     }
    173 
    174     @Override
    175     public void onStopTrackingTouch(SeekBar seekBar) {
    176         mTrackingTouch = false;
    177         if (seekBar.getProgress() != mProgress) {
    178             syncProgress(seekBar);
    179         }
    180     }
    181 
    182     @Override
    183     protected Parcelable onSaveInstanceState() {
    184         /*
    185          * Suppose a client uses this preference type without persisting. We
    186          * must save the instance state so it is able to, for example, survive
    187          * orientation changes.
    188          */
    189 
    190         final Parcelable superState = super.onSaveInstanceState();
    191         if (isPersistent()) {
    192             // No need to save instance state since it's persistent
    193             return superState;
    194         }
    195 
    196         // Save the instance state
    197         final SavedState myState = new SavedState(superState);
    198         myState.progress = mProgress;
    199         myState.max = mMax;
    200         return myState;
    201     }
    202 
    203     @Override
    204     protected void onRestoreInstanceState(Parcelable state) {
    205         if (!state.getClass().equals(SavedState.class)) {
    206             // Didn't save state for us in onSaveInstanceState
    207             super.onRestoreInstanceState(state);
    208             return;
    209         }
    210 
    211         // Restore the instance state
    212         SavedState myState = (SavedState) state;
    213         super.onRestoreInstanceState(myState.getSuperState());
    214         mProgress = myState.progress;
    215         mMax = myState.max;
    216         notifyChanged();
    217     }
    218 
    219     /**
    220      * SavedState, a subclass of {@link BaseSavedState}, will store the state
    221      * of MyPreference, a subclass of Preference.
    222      * <p>
    223      * It is important to always call through to super methods.
    224      */
    225     private static class SavedState extends BaseSavedState {
    226         int progress;
    227         int max;
    228 
    229         public SavedState(Parcel source) {
    230             super(source);
    231 
    232             // Restore the click counter
    233             progress = source.readInt();
    234             max = source.readInt();
    235         }
    236 
    237         @Override
    238         public void writeToParcel(Parcel dest, int flags) {
    239             super.writeToParcel(dest, flags);
    240 
    241             // Save the click counter
    242             dest.writeInt(progress);
    243             dest.writeInt(max);
    244         }
    245 
    246         public SavedState(Parcelable superState) {
    247             super(superState);
    248         }
    249 
    250         @SuppressWarnings("unused")
    251         public static final Parcelable.Creator<SavedState> CREATOR =
    252                 new Parcelable.Creator<SavedState>() {
    253             public SavedState createFromParcel(Parcel in) {
    254                 return new SavedState(in);
    255             }
    256 
    257             public SavedState[] newArray(int size) {
    258                 return new SavedState[size];
    259             }
    260         };
    261     }
    262 }
    263