Skip to content

Instantly share code, notes, and snippets.

@sakurabird
Last active November 29, 2016 15:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sakurabird/ba40e8d4654f44d9f58a to your computer and use it in GitHub Desktop.
Save sakurabird/ba40e8d4654f44d9f58a to your computer and use it in GitHub Desktop.
Implementations of SeekBarPreference features specific to media volume.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="20dp">
<TextView
android:id="@+id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@string/setting_sound2"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary" />
<SeekBar
android:id="@+id/seekbar"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="@string/setting_sound">
<CheckBoxPreference
android:defaultValue="true"
android:key="@string/PREF_SOUND_ON"
android:title="@string/setting_sound_on_title" />
<com.sakurafish.parrot.callconfirm.Pref.SoundSeekBarPreference
android:dependency="@string/PREF_SOUND_ON"
android:key="@string/PREF_SOUND_VOLUME"
android:title="@string/setting_sound_on_title" />
</PreferenceCategory>
</PreferenceScreen>
/**
* Copyright 2015-present Yukari Sakurai
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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 com.sakurafish.parrot.callconfirm.Pref;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.media.AudioManager;
import android.os.Build;
import android.preference.Preference;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;
import com.sakurafish.common.lib.pref.Pref;
import com.sakurafish.parrot.callconfirm.R;
import com.sakurafish.parrot.callconfirm.utils.Utils;
import static android.os.Build.VERSION.SDK_INT;
/**
* Save SeekBar's value to the preference. <br>
* Thanks to MrBIMC's "MaterialSeekBarPreference" <br>
* https://github.com/MrBIMC/MaterialSeekBarPreference
*/
public class SoundSeekBarPreference extends Preference implements SeekBar.OnSeekBarChangeListener {
public interface OnVolumeChangedListerner {
void onChanged();
}
private Context mContext;
private OnVolumeChangedListerner mListerner;
private int mMaxValue = 100;
private int mMinValue = 0;
private int mInterval = 1;
private int mCurrentValue;
private SeekBar mSeekBar;
public SoundSeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setLayoutResource(R.layout.preference_seekbar);
setCurrentVolume();
}
public SoundSeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
setLayoutResource(R.layout.preference_seekbar);
setCurrentVolume();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SoundSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
setLayoutResource(R.layout.preference_seekbar);
setCurrentVolume();
}
public void setOnVolumeChangedListerner(OnVolumeChangedListerner listerner) {
mListerner = listerner;
}
public void removeOnVolumeChangedListerner() {
mListerner = null;
}
private void setCurrentVolume() {
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
if (Pref.isExistKey(mContext, mContext.getString(R.string.PREF_SOUND_VOLUME))) {
mCurrentValue = Pref.getPrefInt(mContext, mContext.getString(R.string.PREF_SOUND_VOLUME));
} else {
mCurrentValue = am.getStreamVolume(AudioManager.STREAM_MUSIC);
}
mMaxValue = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
Utils.logDebug("mCurrentValue:" + mCurrentValue + " mMaxValue:" + mMaxValue + " sysvol:" + am.getStreamVolume(AudioManager.STREAM_MUSIC));
}
@Override
public void onBindView(@NonNull View view) {
super.onBindView(view);
mSeekBar = (SeekBar) view.findViewById(R.id.seekbar);
mSeekBar.setMax(mMaxValue - mMinValue);
mSeekBar.setOnSeekBarChangeListener(this);
mSeekBar.setProgress(mCurrentValue - mMinValue);
setSeekBarTintOnPreLollipop();
if (!view.isEnabled()) {
mSeekBar.setEnabled(false);
}
}
public void setCurrentValue(int value) {
mCurrentValue = value;
super.persistInt(value);
notifyChanged();
}
public int getCurrentValue() {
return mCurrentValue;
}
static int pxFromDp(int dp, Context context) {
return (int) (dp * context.getResources().getDisplayMetrics().density);
}
void setSeekBarTintOnPreLollipop() { //TMP: I hope google will introduce native seekbar tinting for appcompat users
if (SDK_INT < 21) {
Resources.Theme theme = getContext().getTheme();
int attr = R.attr.colorAccent;
int fallbackColor = Color.parseColor("#009688");
int accent = theme.obtainStyledAttributes(new int[]{attr}).getColor(0, fallbackColor);
ShapeDrawable thumb = new ShapeDrawable(new OvalShape());
thumb.setIntrinsicHeight(pxFromDp(15, getContext()));
thumb.setIntrinsicWidth(pxFromDp(15, getContext()));
thumb.setColorFilter(new PorterDuffColorFilter(accent, PorterDuff.Mode.SRC_ATOP));
mSeekBar.setThumb(thumb);
Drawable progress = mSeekBar.getProgressDrawable();
progress.setColorFilter(new PorterDuffColorFilter(accent, PorterDuff.Mode.MULTIPLY));
mSeekBar.setProgressDrawable(progress);
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int newValue = progress + mMinValue;
if (newValue > mMaxValue) newValue = mMaxValue;
else if (newValue < mMinValue) newValue = mMinValue;
else if (mInterval != 1 && newValue % mInterval != 0)
newValue = Math.round(((float) newValue) / mInterval) * mInterval;
// change rejected, revert to the previous value
if (!callChangeListener(newValue)) {
seekBar.setProgress(mCurrentValue - mMinValue);
return;
}
// change accepted, store it
mCurrentValue = newValue;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
notifyChanged();
persistInt(mCurrentValue);
if (mListerner != null) {
mListerner.onChanged();
}
}
}
final SoundSeekBarPreference volume = (SoundSeekBarPreference) findPreference(getString(R.string.PREF_SOUND_VOLUME));
volume.setOnVolumeChangedListerner(new SoundSeekBarPreference.OnVolumeChangedListerner() {
@Override
public void onChanged() {
int index = Integer.parseInt(Pref.getPrefString(mContext, mContext.getString(R.string.PREF_SOUND)));
int voiceIdx = MyApplication.getSoundIds()[index];
MyApplication.getSoundManager().stop(voiceIdx);
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
int newVolume = Pref.getPrefInt(mContext, mContext.getString(R.string.PREF_SOUND_VOLUME));
am.setStreamVolume(AudioManager.STREAM_MUSIC, newVolume, 0);
MyApplication.getSoundManager().play(voiceIdx);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment