Mercurial > gmapzoominvert
diff XposedLibrary/src/de/robv/android/xposed/library/ui/ValueSeekBarPreference.java @ 0:3da8a7a621cd
Initial commit
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Mon, 20 Jan 2014 22:56:13 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/XposedLibrary/src/de/robv/android/xposed/library/ui/ValueSeekBarPreference.java Mon Jan 20 22:56:13 2014 -0600 @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.robv.android.xposed.library.ui; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.preference.Preference; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import de.robv.android.xposed.library.R; + +public class ValueSeekBarPreference extends Preference implements OnSeekBarChangeListener { + + private int mProgress; + private int mStep; + private int mMin; + private int mMax; + private String valueDisplayFormat; + private boolean mTrackingTouch; + private TextView tvValue; + + public ValueSeekBarPreference( + Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + if (attrs != null) { + setStep(attrs.getAttributeIntValue(null, "step", 1)); + setMin(attrs.getAttributeIntValue(null, "min", 0)); + setMax(attrs.getAttributeIntValue(null, "max", 100)); + valueDisplayFormat = attrs.getAttributeValue(null, "displayFormat"); + if (valueDisplayFormat == null) + valueDisplayFormat = "%d"; + } + } + + public ValueSeekBarPreference(Context context, AttributeSet attrs) { + this(context, attrs, android.R.attr.preferenceStyle); + } + + public ValueSeekBarPreference(Context context) { + this(context, null); + } + + @Override + protected View onCreateView(ViewGroup parent) { + ViewGroup originalView = (ViewGroup) super.onCreateView(parent); + + final LayoutInflater layoutInflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + ViewGroup newlayout = (ViewGroup) layoutInflater.inflate(R.layout.preference_valueseekbar_extension, null); + newlayout.addView(originalView, 0); + + tvValue = (TextView) newlayout.findViewById(R.id.valueseekbar_preference_value); + + return newlayout; + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + SeekBar seekBar = (SeekBar) view.findViewById(R.id.valueseekbar_preference_seekbar); + seekBar.setOnSeekBarChangeListener(this); + seekBar.setMax((mMax - mMin) / mStep); + seekBar.setProgress((mProgress - mMin) / mStep); + tvValue.setText(String.format(valueDisplayFormat, mProgress)); + seekBar.setEnabled(isEnabled()); + } + + @Override + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + setProgress(restoreValue ? getPersistedInt(mProgress) + : (Integer) defaultValue); + } + + @Override + protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getInt(index, 0); + } + + public void setStep(int step) { + if (step != mStep) { + mStep = step; + notifyChanged(); + } + } + + public void setMin(int min) { + if (min != mMin) { + mMin = min; + notifyChanged(); + } + } + + public void setMax(int max) { + if (max != mMax) { + mMax = max; + notifyChanged(); + } + } + + public void setProgress(int progress) { + setProgress(progress, true); + } + + private void setProgress(int progress, boolean notifyChanged) { + if (progress > mMax) { + progress = mMax; + } + if (progress < mMin) { + progress = mMin; + } + if (progress != mProgress) { + mProgress = progress; + persistInt(progress); + if (notifyChanged) { + notifyChanged(); + } + } + } + + public int getProgress() { + return mProgress; + } + + /** + * Persist the seekBar's progress value if callChangeListener + * returns true, otherwise set the seekBar's progress to the stored value + */ + void syncProgress(SeekBar seekBar) { + int progress = seekBar.getProgress() * mStep + mMin; + if (progress != mProgress) { + if (callChangeListener(progress)) { + setProgress(progress, false); + } else { + seekBar.setProgress((mProgress - mMin) / mStep); + } + } + } + + @Override + public void onProgressChanged( + SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser && !mTrackingTouch) { + syncProgress(seekBar); + } + tvValue.setText(String.format(valueDisplayFormat, progress * mStep + mMin)); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + mTrackingTouch = true; + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + mTrackingTouch = false; + if (seekBar.getProgress() * mStep + mMin != mProgress) { + syncProgress(seekBar); + } + } + + @Override + protected Parcelable onSaveInstanceState() { + /* + * Suppose a client uses this preference type without persisting. We + * must save the instance state so it is able to, for example, survive + * orientation changes. + */ + + final Parcelable superState = super.onSaveInstanceState(); + if (isPersistent()) { + // No need to save instance state since it's persistent + return superState; + } + + // Save the instance state + final SavedState myState = new SavedState(superState); + myState.progress = mProgress; + myState.step = mStep; + myState.min = mMin; + myState.max = mMax; + return myState; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (!state.getClass().equals(SavedState.class)) { + // Didn't save state for us in onSaveInstanceState + super.onRestoreInstanceState(state); + return; + } + + // Restore the instance state + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + mProgress = myState.progress; + mStep = myState.step; + mMin = myState.min; + mMax = myState.max; + notifyChanged(); + } + + /** + * SavedState, a subclass of {@link BaseSavedState}, will store the state + * of MyPreference, a subclass of Preference. + * <p> + * It is important to always call through to super methods. + */ + private static class SavedState extends BaseSavedState { + int progress; + int step; + int min; + int max; + + public SavedState(Parcel source) { + super(source); + + // Restore the click counter + progress = source.readInt(); + step = source.readInt(); + min = source.readInt(); + max = source.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + + dest.writeInt(progress); + dest.writeInt(step); + dest.writeInt(min); + dest.writeInt(max); + } + + public SavedState(Parcelable superState) { + super(superState); + } + + @SuppressWarnings("unused") + public static final Parcelable.Creator<SavedState> CREATOR = + new Parcelable.Creator<SavedState>() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +}