ar.rulosoft.custompref.SeekBarCustomPreference.java Source code

Java tutorial

Introduction

Here is the source code for ar.rulosoft.custompref.SeekBarCustomPreference.java

Source

/*
 * 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.
 *
 * https://github.com/consp1racy/android-support-preference
 */

package ar.rulosoft.custompref;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

import java.util.Map;
import java.util.WeakHashMap;

import ar.rulosoft.mimanganu.R;

/*
 * 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.
 * https://github.com/consp1racy/android-support-preference/blob/master/library/src/main/java/net/xpece/android/support/preference/SeekBarPreference.java
 */

public class SeekBarCustomPreference extends Preference implements OnSeekBarChangeListener, View.OnKeyListener {

    // A filthy hack so we can update info text while dragging seek bar thumb.
    private static final WeakHashMap<TextView, SeekBarCustomPreference> mInfoViews = new WeakHashMap<>();
    private static final WeakHashMap<String, SeekBarCustomPreference> mKeys = new WeakHashMap<>();
    private int mProgress;
    private int mPreferredMin = 0;
    private int mPreferredMax = 100;
    private boolean mTrackingTouch;
    private CharSequence mInfo;
    private OnSeekBarChangeListener mOnSeekBarChangeListener;
    private int mKeyProgressIncrement;

    public SeekBarCustomPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs, defStyleAttr, defStyleRes);
    }

    public SeekBarCustomPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public SeekBarCustomPreference(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.seekBarPreferenceStyle);
    }

    public SeekBarCustomPreference(Context context) {
        this(context, null);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomDialogPref, defStyleAttr,
                defStyleRes);
        setMax(a.getInt(R.styleable.CustomDialogPref_val_max, mPreferredMax));
        setMin(a.getInt(R.styleable.CustomDialogPref_val_min, mPreferredMin));
        a.recycle();
        setLayoutResource(R.layout.preference_seekbar_widget_layout);
    }

    @Override
    public void onBindViewHolder(final PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);

        holder.itemView.setClickable(false);

        SeekBar seekBar = (SeekBar) holder.findViewById(R.id.seekbar);
        seekBar.setOnSeekBarChangeListener(this);
        seekBar.setMax(mPreferredMax - mPreferredMin);
        seekBar.setProgress(mProgress - mPreferredMin);
        seekBar.setEnabled(isEnabled());

        mKeyProgressIncrement = seekBar.getKeyProgressIncrement();
        holder.itemView.setOnKeyListener(this);

        TextView info = (TextView) holder.findViewById(android.R.id.summary);
        if (info != null) {
            mInfoViews.put(info, this);
            bindInfo(info);
            mKeys.put(getKey(), this);
        }
    }

    private void bindInfo(@NonNull TextView info) {
        info.setText(getSummary());
    }

    public CharSequence getInfo() {
        return mInfo;
    }

    public void setInfo(CharSequence info) {
        if (info == null && this.mInfo != null || info != null && !info.equals(this.mInfo)) {
            mInfo = info;
            onInfoChanged();
        }
    }

    public void onInfoChanged() {
        // DO NOT call notifyChanged()!
        for (Map.Entry<TextView, SeekBarCustomPreference> entry : mInfoViews.entrySet()) {
            TextView tv = entry.getKey();
            SeekBarCustomPreference pref = entry.getValue();
            if (pref == this) {
                bindInfo(tv);
            }
        }
    }

    public TextView getTV() {
        // DO NOT call notifyChanged()!
        for (Map.Entry<TextView, SeekBarCustomPreference> entry : mInfoViews.entrySet()) {
            TextView tv = entry.getKey();
            SeekBarCustomPreference pref = entry.getValue();
            if (pref == this) {
                return tv;
            }
        }
        return null;
    }

    public OnSeekBarChangeListener getOnSeekBarChangeListener() {
        return mOnSeekBarChangeListener;
    }

    public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
        mOnSeekBarChangeListener = listener;
        onInfoChanged();
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (isEnabled()) {
            if (event.getAction() != KeyEvent.ACTION_UP) {
                int increment = mKeyProgressIncrement;

                switch (keyCode) {
                case KeyEvent.KEYCODE_PLUS:
                case KeyEvent.KEYCODE_EQUALS:
                    setProgress(getProgress() + increment);
                    return true;
                case KeyEvent.KEYCODE_MINUS:
                    setProgress(getProgress() - increment);
                    return true;
                case KeyEvent.KEYCODE_DPAD_LEFT:
                    increment = -increment;
                    // fallthrough
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                    increment = ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_RTL ? -increment
                            : increment;
                    setProgress(getProgress() + increment);
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        setProgress(restoreValue ? Integer.parseInt(getPersistedString(mProgress + "")) : (Integer) defaultValue);
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getInt(index, 0);
    }

    public int getMin() {
        return mPreferredMin;
    }

    public void setMin(int min) {
        if (min != mPreferredMin) {
            mPreferredMin = min;
            notifyChanged();
        }
    }

    public int getMax() {
        return mPreferredMax;
    }

    public void setMax(int max) {
        if (max != mPreferredMax) {
            mPreferredMax = max;
            notifyChanged();
        }
    }

    private void setProgress(int preferredProgress, boolean notifyChanged) {
        if (preferredProgress > mPreferredMax) {
            preferredProgress = mPreferredMax;
        }
        if (preferredProgress < mPreferredMin) {
            preferredProgress = mPreferredMin;
        }
        if (preferredProgress != mProgress) {
            mProgress = preferredProgress;
            persistString("" + preferredProgress);
            //            Log.d("SBP", "preferredProgress=" + preferredProgress);
            if (notifyChanged) {
                notifyChanged();
            }
        }
    }

    public int getProgress() {
        return mProgress;
    }

    public void setProgress(int progress) {
        setProgress(progress, true);
    }

    /**
     * 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();
        if (progress != mProgress - mPreferredMin) {
            if (callChangeListener(progress)) {
                setProgress(progress + mPreferredMin, false);
            } else {
                seekBar.setProgress(mProgress - mPreferredMin);
            }
        }
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if (fromUser && !mTrackingTouch) {
            syncProgress(seekBar);
        }
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onProgressChanged(seekBar, progress + mPreferredMin, fromUser);
        }
        if (fromUser) {
            TextView tv = getTV();
            if (tv != null) {
                tv.setText(String.format(super.getSummary().toString(), progress + mPreferredMin));
                for (Map.Entry<String, SeekBarCustomPreference> entry : mKeys.entrySet()) {
                    String k = entry.getKey();
                    SeekBarCustomPreference pref = entry.getValue();
                    if (pref == this) {
                        setKey(k);
                        int persist = progress + mPreferredMin;
                        persistString("" + persist);
                    }
                }
            }
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        mTrackingTouch = true;
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
        }
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        mTrackingTouch = false;
        if (seekBar.getProgress() != mProgress) {
            syncProgress(seekBar);
        }
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onStopTrackingTouch(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.max = mPreferredMax;
        myState.min = mPreferredMin;
        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());
        mPreferredMax = myState.max;
        mPreferredMin = myState.min;
        setProgress(myState.progress, true);
    }

    @Override
    public CharSequence getSummary() {
        final Integer entry = getProgress();
        if (super.getSummary() == null) {
            return super.getSummary();
        } else {
            return String.format(super.getSummary().toString(), entry);
        }
    }

    /**
     * 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 {
        @SuppressWarnings("unused")
        public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
        int progress;
        int max;
        int min;

        public SavedState(Parcel source) {
            super(source);

            // Restore the click counter
            progress = source.readInt();
            max = source.readInt();
            min = source.readInt();
        }

        public SavedState(Parcelable superState) {
            super(superState);
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);

            // Save the click counter
            dest.writeInt(progress);
            dest.writeInt(max);
            dest.writeInt(min);
        }
    }

}