Perform haptic feedback when the seekbar snaps.
- add haptic feedback mode to perform haptic feedback as the seekbar's progress value is updated. - add haptic feedback mode to perform haptic feedback as the seekbar's progress value is equal to the min/max value Bug: 172900709 Test: make -j42 RunSettingsRoboTests ROBOTEST_FILTER=SeekBarPreferenceTest Change-Id: I9378313d366f09bb8e7069d9240fde24af318c53
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.widget;
|
||||
|
||||
import static android.view.HapticFeedbackConstants.CLOCK_TICK;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Parcel;
|
||||
@@ -39,12 +41,17 @@ import com.android.settingslib.RestrictedPreference;
|
||||
public class SeekBarPreference extends RestrictedPreference
|
||||
implements OnSeekBarChangeListener, View.OnKeyListener {
|
||||
|
||||
public static final int HAPTIC_FEEDBACK_MODE_NONE = 0;
|
||||
public static final int HAPTIC_FEEDBACK_MODE_ON_TICKS = 1;
|
||||
public static final int HAPTIC_FEEDBACK_MODE_ON_ENDS = 2;
|
||||
|
||||
private int mProgress;
|
||||
private int mMax;
|
||||
private int mMin;
|
||||
private boolean mTrackingTouch;
|
||||
|
||||
private boolean mContinuousUpdates;
|
||||
private int mHapticFeedbackMode = HAPTIC_FEEDBACK_MODE_NONE;
|
||||
private int mDefaultProgress = -1;
|
||||
|
||||
private SeekBar mSeekBar;
|
||||
@@ -235,6 +242,17 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
mContinuousUpdates = continuousUpdates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the haptic feedback mode. HAPTIC_FEEDBACK_MODE_ON_TICKS means to perform haptic feedback
|
||||
* as the SeekBar's progress is updated; HAPTIC_FEEDBACK_MODE_ON_ENDS means to perform haptic
|
||||
* feedback as the SeekBar's progress value is equal to the min/max value.
|
||||
*
|
||||
* @param hapticFeedbackMode the haptic feedback mode.
|
||||
*/
|
||||
public void setHapticFeedbackMode(int hapticFeedbackMode) {
|
||||
mHapticFeedbackMode = hapticFeedbackMode;
|
||||
}
|
||||
|
||||
private void setProgress(int progress, boolean notifyChanged) {
|
||||
if (progress > mMax) {
|
||||
progress = mMax;
|
||||
@@ -264,6 +282,16 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
if (progress != mProgress) {
|
||||
if (callChangeListener(progress)) {
|
||||
setProgress(progress, false);
|
||||
switch (mHapticFeedbackMode) {
|
||||
case HAPTIC_FEEDBACK_MODE_ON_TICKS:
|
||||
seekBar.performHapticFeedback(CLOCK_TICK);
|
||||
break;
|
||||
case HAPTIC_FEEDBACK_MODE_ON_ENDS:
|
||||
if (progress == mMax || progress == mMin) {
|
||||
seekBar.performHapticFeedback(CLOCK_TICK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
seekBar.setProgress(mProgress);
|
||||
}
|
||||
|
@@ -16,15 +16,21 @@
|
||||
|
||||
package com.android.settings.widget;
|
||||
|
||||
import static android.view.HapticFeedbackConstants.CLOCK_TICK;
|
||||
import static android.view.HapticFeedbackConstants.CONTEXT_CLICK;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
@@ -46,9 +52,11 @@ public class SeekBarPreferenceTest {
|
||||
private static final int MAX = 75;
|
||||
private static final int MIN = 5;
|
||||
private static final int PROGRESS = 16;
|
||||
private static final int NEW_PROGRESS = 17;
|
||||
|
||||
private Context mContext;
|
||||
private SeekBarPreference mSeekBarPreference;
|
||||
private SeekBar mSeekBar;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -60,6 +68,11 @@ public class SeekBarPreferenceTest {
|
||||
mSeekBarPreference.setMin(MIN);
|
||||
mSeekBarPreference.setProgress(PROGRESS);
|
||||
mSeekBarPreference.setPersistent(false);
|
||||
mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_NONE);
|
||||
|
||||
mSeekBar = new SeekBar(mContext);
|
||||
mSeekBar.setMax(MAX);
|
||||
mSeekBar.setMin(MIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -118,6 +131,53 @@ public class SeekBarPreferenceTest {
|
||||
verify(mSeekBarPreference).setSeekBarStateDescription("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProgressChanged_hapticFeedbackModeNone_clockTickFeedbackNotPerformed() {
|
||||
mSeekBar.setProgress(NEW_PROGRESS);
|
||||
when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
|
||||
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
|
||||
|
||||
mSeekBarPreference.onProgressChanged(mSeekBar, NEW_PROGRESS, true);
|
||||
|
||||
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isNotEqualTo(CLOCK_TICK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProgressChanged_hapticFeedbackModeOnTicks_clockTickFeedbackPerformed() {
|
||||
mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS);
|
||||
mSeekBar.setProgress(NEW_PROGRESS);
|
||||
when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
|
||||
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
|
||||
|
||||
mSeekBarPreference.onProgressChanged(mSeekBar, NEW_PROGRESS, true);
|
||||
|
||||
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProgressChanged_hapticFeedbackModeOnEnds_clockTickFeedbackNotPerformed() {
|
||||
mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_ENDS);
|
||||
mSeekBar.setProgress(NEW_PROGRESS);
|
||||
when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
|
||||
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
|
||||
|
||||
mSeekBarPreference.onProgressChanged(mSeekBar, NEW_PROGRESS, true);
|
||||
|
||||
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isNotEqualTo(CLOCK_TICK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onProgressChanged_hapticFeedbackModeOnEndsAndMinValue_clockTickFeedbackPerformed() {
|
||||
mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_ENDS);
|
||||
mSeekBar.setProgress(MIN);
|
||||
when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
|
||||
mSeekBar.performHapticFeedback(CONTEXT_CLICK);
|
||||
|
||||
mSeekBarPreference.onProgressChanged(mSeekBar, MIN, true);
|
||||
|
||||
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
|
||||
}
|
||||
|
||||
public static class TestFragment extends PreferenceFragmentCompat {
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
|
Reference in New Issue
Block a user