VolumePreference.java revision 735f9ebc188e1cb225533e1f5f9ef925d1f0b20e
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.start(); 71 mSeekBarVolumizer.setSeekBar(seekBar); 72 73 getPreferenceManager().registerOnActivityStopListener(this); 74 75 // grab focus and key events so that pressing the volume buttons in the 76 // dialog doesn't also show the normal volume adjust toast. 77 view.setOnKeyListener(this); 78 view.setFocusableInTouchMode(true); 79 view.requestFocus(); 80 } 81 82 public boolean onKey(View v, int keyCode, KeyEvent event) { 83 // If key arrives immediately after the activity has been cleaned up. 84 if (mSeekBarVolumizer == null) return true; 85 boolean isdown = (event.getAction() == KeyEvent.ACTION_DOWN); 86 switch (keyCode) { 87 case KeyEvent.KEYCODE_VOLUME_DOWN: 88 if (isdown) { 89 mSeekBarVolumizer.changeVolumeBy(-1); 90 } 91 return true; 92 case KeyEvent.KEYCODE_VOLUME_UP: 93 if (isdown) { 94 mSeekBarVolumizer.changeVolumeBy(1); 95 } 96 return true; 97 case KeyEvent.KEYCODE_VOLUME_MUTE: 98 if (isdown) { 99 mSeekBarVolumizer.muteVolume(); 100 } 101 return true; 102 default: 103 return false; 104 } 105 } 106 107 @Override 108 protected void onDialogClosed(boolean positiveResult) { 109 super.onDialogClosed(positiveResult); 110 111 if (!positiveResult && mSeekBarVolumizer != null) { 112 mSeekBarVolumizer.revertVolume(); 113 } 114 115 cleanup(); 116 } 117 118 public void onActivityStop() { 119 if (mSeekBarVolumizer != null) { 120 mSeekBarVolumizer.stopSample(); 121 } 122 } 123 124 /** 125 * Do clean up. This can be called multiple times! 126 */ 127 private void cleanup() { 128 getPreferenceManager().unregisterOnActivityStopListener(this); 129 130 if (mSeekBarVolumizer != null) { 131 Dialog dialog = getDialog(); 132 if (dialog != null && dialog.isShowing()) { 133 View view = dialog.getWindow().getDecorView() 134 .findViewById(com.android.internal.R.id.seekbar); 135 if (view != null) view.setOnKeyListener(null); 136 // Stopped while dialog was showing, revert changes 137 mSeekBarVolumizer.revertVolume(); 138 } 139 mSeekBarVolumizer.stop(); 140 mSeekBarVolumizer = null; 141 } 142 143 } 144 145 @Override 146 public void onSampleStarting(SeekBarVolumizer volumizer) { 147 if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) { 148 mSeekBarVolumizer.stopSample(); 149 } 150 } 151 152 @Override 153 protected Parcelable onSaveInstanceState() { 154 final Parcelable superState = super.onSaveInstanceState(); 155 if (isPersistent()) { 156 // No need to save instance state since it's persistent 157 return superState; 158 } 159 160 final SavedState myState = new SavedState(superState); 161 if (mSeekBarVolumizer != null) { 162 mSeekBarVolumizer.onSaveInstanceState(myState.getVolumeStore()); 163 } 164 return myState; 165 } 166 167 @Override 168 protected void onRestoreInstanceState(Parcelable state) { 169 if (state == null || !state.getClass().equals(SavedState.class)) { 170 // Didn't save state for us in onSaveInstanceState 171 super.onRestoreInstanceState(state); 172 return; 173 } 174 175 SavedState myState = (SavedState) state; 176 super.onRestoreInstanceState(myState.getSuperState()); 177 if (mSeekBarVolumizer != null) { 178 mSeekBarVolumizer.onRestoreInstanceState(myState.getVolumeStore()); 179 } 180 } 181 182 public static class VolumeStore { 183 public int volume = -1; 184 public int originalVolume = -1; 185 } 186 187 private static class SavedState extends BaseSavedState { 188 VolumeStore mVolumeStore = new VolumeStore(); 189 190 public SavedState(Parcel source) { 191 super(source); 192 mVolumeStore.volume = source.readInt(); 193 mVolumeStore.originalVolume = source.readInt(); 194 } 195 196 @Override 197 public void writeToParcel(Parcel dest, int flags) { 198 super.writeToParcel(dest, flags); 199 dest.writeInt(mVolumeStore.volume); 200 dest.writeInt(mVolumeStore.originalVolume); 201 } 202 203 VolumeStore getVolumeStore() { 204 return mVolumeStore; 205 } 206 207 public SavedState(Parcelable superState) { 208 super(superState); 209 } 210 211 public static final Parcelable.Creator<SavedState> CREATOR = 212 new Parcelable.Creator<SavedState>() { 213 public SavedState createFromParcel(Parcel in) { 214 return new SavedState(in); 215 } 216 217 public SavedState[] newArray(int size) { 218 return new SavedState[size]; 219 } 220 }; 221 } 222} 223