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