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