VolumePreference.java revision 95caba127051845ff1e26d7e64909db89408e8e7
1/* 2 * Copyright (C) 2007 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 17package android.preference; 18 19import android.app.Dialog; 20import android.content.Context; 21import android.content.res.TypedArray; 22import android.os.Parcel; 23import android.os.Parcelable; 24import android.util.AttributeSet; 25import android.view.KeyEvent; 26import android.view.View; 27import android.widget.SeekBar; 28 29/** 30 * @hide 31 */ 32public class VolumePreference extends SeekBarDialogPreference implements 33 PreferenceManager.OnActivityStopListener, View.OnKeyListener, SeekBarVolumizer.Callback { 34 35 static final String TAG = "VolumePreference"; 36 37 private int mStreamType; 38 39 /** May be null if the dialog isn't visible. */ 40 private SeekBarVolumizer mSeekBarVolumizer; 41 42 public VolumePreference( 43 Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 44 super(context, attrs, defStyleAttr, defStyleRes); 45 46 final TypedArray a = context.obtainStyledAttributes(attrs, 47 com.android.internal.R.styleable.VolumePreference, defStyleAttr, defStyleRes); 48 mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0); 49 a.recycle(); 50 } 51 52 public VolumePreference(Context context, AttributeSet attrs, int defStyleAttr) { 53 this(context, attrs, defStyleAttr, 0); 54 } 55 56 public VolumePreference(Context context, AttributeSet attrs) { 57 this(context, attrs, com.android.internal.R.attr.dialogPreferenceStyle); 58 } 59 60 public void setStreamType(int streamType) { 61 mStreamType = streamType; 62 } 63 64 @Override 65 protected void onBindDialogView(View view) { 66 super.onBindDialogView(view); 67 68 final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); 69 mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this); 70 mSeekBarVolumizer.setSeekBar(seekBar); 71 72 getPreferenceManager().registerOnActivityStopListener(this); 73 74 // grab focus and key events so that pressing the volume buttons in the 75 // dialog doesn't also show the normal volume adjust toast. 76 view.setOnKeyListener(this); 77 view.setFocusableInTouchMode(true); 78 view.requestFocus(); 79 } 80 81 public boolean onKey(View v, int keyCode, KeyEvent event) { 82 // If key arrives immediately after the activity has been cleaned up. 83 if (mSeekBarVolumizer == null) return true; 84 boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN); 85 switch (keyCode) { 86 case KeyEvent.KEYCODE_VOLUME_DOWN: 87 if (isdown) { 88 mSeekBarVolumizer.changeVolumeBy(-1); 89 } 90 return true; 91 case KeyEvent.KEYCODE_VOLUME_UP: 92 if (isdown) { 93 mSeekBarVolumizer.changeVolumeBy(1); 94 } 95 return true; 96 case KeyEvent.KEYCODE_VOLUME_MUTE: 97 if (isdown) { 98 mSeekBarVolumizer.muteVolume(); 99 } 100 return true; 101 default: 102 return false; 103 } 104 } 105 106 @Override 107 protected void onDialogClosed(boolean positiveResult) { 108 super.onDialogClosed(positiveResult); 109 110 if (!positiveResult && mSeekBarVolumizer != null) { 111 mSeekBarVolumizer.revertVolume(); 112 } 113 114 cleanup(); 115 } 116 117 public void onActivityStop() { 118 if (mSeekBarVolumizer != null) { 119 mSeekBarVolumizer.postStopSample(); 120 } 121 } 122 123 /** 124 * Do clean up. This can be called multiple times! 125 */ 126 private void cleanup() { 127 getPreferenceManager().unregisterOnActivityStopListener(this); 128 129 if (mSeekBarVolumizer != null) { 130 Dialog dialog = getDialog(); 131 if (dialog != null && dialog.isShowing()) { 132 View view = dialog.getWindow().getDecorView() 133 .findViewById(com.android.internal.R.id.seekbar); 134 if (view != null) view.setOnKeyListener(null); 135 // Stopped while dialog was showing, revert changes 136 mSeekBarVolumizer.revertVolume(); 137 } 138 mSeekBarVolumizer.stop(); 139 mSeekBarVolumizer = null; 140 } 141 142 } 143 144 @Override 145 public void onSampleStarting(SeekBarVolumizer volumizer) { 146 if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) { 147 mSeekBarVolumizer.stopSample(); 148 } 149 } 150 151 @Override 152 protected Parcelable onSaveInstanceState() { 153 final Parcelable superState = super.onSaveInstanceState(); 154 if (isPersistent()) { 155 // No need to save instance state since it's persistent 156 return superState; 157 } 158 159 final SavedState myState = new SavedState(superState); 160 if (mSeekBarVolumizer != null) { 161 mSeekBarVolumizer.onSaveInstanceState(myState.getVolumeStore()); 162 } 163 return myState; 164 } 165 166 @Override 167 protected void onRestoreInstanceState(Parcelable state) { 168 if (state == null || !state.getClass().equals(SavedState.class)) { 169 // Didn't save state for us in onSaveInstanceState 170 super.onRestoreInstanceState(state); 171 return; 172 } 173 174 SavedState myState = (SavedState) state; 175 super.onRestoreInstanceState(myState.getSuperState()); 176 if (mSeekBarVolumizer != null) { 177 mSeekBarVolumizer.onRestoreInstanceState(myState.getVolumeStore()); 178 } 179 } 180 181 public static class VolumeStore { 182 public int volume = -1; 183 public int originalVolume = -1; 184 } 185 186 private static class SavedState extends BaseSavedState { 187 VolumeStore mVolumeStore = new VolumeStore(); 188 189 public SavedState(Parcel source) { 190 super(source); 191 mVolumeStore.volume = source.readInt(); 192 mVolumeStore.originalVolume = source.readInt(); 193 } 194 195 @Override 196 public void writeToParcel(Parcel dest, int flags) { 197 super.writeToParcel(dest, flags); 198 dest.writeInt(mVolumeStore.volume); 199 dest.writeInt(mVolumeStore.originalVolume); 200 } 201 202 VolumeStore getVolumeStore() { 203 return mVolumeStore; 204 } 205 206 public SavedState(Parcelable superState) { 207 super(superState); 208 } 209 210 public static final Parcelable.Creator<SavedState> CREATOR = 211 new Parcelable.Creator<SavedState>() { 212 public SavedState createFromParcel(Parcel in) { 213 return new SavedState(in); 214 } 215 216 public SavedState[] newArray(int size) { 217 return new SavedState[size]; 218 } 219 }; 220 } 221} 222