mirror of
https://github.com/material-components/material-components-android.git
synced 2026-01-19 19:41:35 +08:00
[Slider] Add missing functionality from SeekBar regarding touch events and value changes
Resolves https://github.com/material-components/material-components-android/pull/831 GIT_ORIGIN_REV_ID=70dd0a10ef204837b01ed9593cfdd9bcf9137228 Co-authored-by: cketcham <cketcham@gmail.com> PiperOrigin-RevId: 287545665
This commit is contained in:
parent
a011ace28f
commit
cde09d4b4e
@ -55,8 +55,8 @@ public class SliderContinuousDemoFragment extends DemoFragment {
|
||||
final String valueFormat) {
|
||||
final TextView sliderValue = view.findViewById(valueId);
|
||||
final Slider slider = view.findViewById(sliderId);
|
||||
slider.setOnChangeListener(
|
||||
(slider1, value) -> sliderValue.setText(String.format(valueFormat, value)));
|
||||
slider.addOnChangeListener(
|
||||
(slider1, value, fromUser) -> sliderValue.setText(String.format(valueFormat, value)));
|
||||
slider.setValue(slider.getValueFrom());
|
||||
SwitchCompat switchButton = view.findViewById(switchId);
|
||||
switchButton.setOnCheckedChangeListener(
|
||||
|
||||
@ -25,6 +25,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import com.google.android.material.slider.Slider;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import io.material.catalog.feature.DemoFragment;
|
||||
|
||||
/** A fragment that displays the main Slider demo for the Catalog app. */
|
||||
@ -37,6 +38,21 @@ public class SliderMainDemoFragment extends DemoFragment {
|
||||
layoutInflater.inflate(R.layout.cat_slider_fragment, viewGroup, false /* attachToRoot */);
|
||||
|
||||
Slider slider = view.findViewById(R.id.slider);
|
||||
slider.addOnSliderTouchListener(
|
||||
new Slider.OnSliderTouchListener() {
|
||||
@Override
|
||||
public void onStartTrackingTouch(Slider slider) {
|
||||
Snackbar.make(
|
||||
slider, R.string.cat_slider_start_touch_description, Snackbar.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(Slider slider) {
|
||||
Snackbar.make(slider, R.string.cat_slider_stop_touch_description, Snackbar.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
Button button = view.findViewById(R.id.button);
|
||||
|
||||
button.setOnClickListener(v -> slider.setValue(slider.getValueTo()));
|
||||
|
||||
@ -34,4 +34,7 @@
|
||||
<string name="cat_slider_title_3" description="The title for a demonstration slider">Negative numbers!</string>
|
||||
<string name="cat_slider_title_4" description="The title for a demonstration slider">With a label formatter</string>
|
||||
<string name="cat_slider_title_5" description="The title for a demonstration slider">I can has decimal numbers?</string>
|
||||
<string name="cat_slider_start_touch_description" description="Indicates the slider is now being touched">Slider started being touched</string>
|
||||
<string name="cat_slider_stop_touch_description" description="Indicates the slider stopped being touched">Slider stopped being touched</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@ -68,6 +68,8 @@ import com.google.android.material.shape.ShapeAppearanceModel;
|
||||
import com.google.android.material.tooltip.TooltipDrawable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@ -186,6 +188,8 @@ public class Slider extends View {
|
||||
@NonNull private final Paint activeTicksPaint;
|
||||
|
||||
@NonNull private TooltipDrawable label;
|
||||
@NonNull private List<OnChangeListener> changeListeners = new ArrayList<>();
|
||||
@NonNull private List<OnSliderTouchListener> touchListeners = new ArrayList<>();
|
||||
|
||||
private final int scaledTouchSlop;
|
||||
|
||||
@ -198,7 +202,6 @@ public class Slider extends View {
|
||||
private int haloRadius;
|
||||
private int labelPadding;
|
||||
private float touchDownX;
|
||||
private OnChangeListener listener;
|
||||
private LabelFormatter formatter;
|
||||
private boolean thumbIsPressed = false;
|
||||
private float valueFrom;
|
||||
@ -241,7 +244,17 @@ public class Slider extends View {
|
||||
|
||||
/** Interface definition for a callback invoked when a slider's value is changed. */
|
||||
public interface OnChangeListener {
|
||||
void onValueChange(Slider slider, float value);
|
||||
void onValueChange(@NonNull Slider slider, float value, boolean fromUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for callbacks invoked when a slider's touch event is being
|
||||
* started/stopped.
|
||||
*/
|
||||
public interface OnSliderTouchListener {
|
||||
void onStartTrackingTouch(@NonNull Slider slider);
|
||||
|
||||
void onStopTrackingTouch(@NonNull Slider slider);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -538,9 +551,7 @@ public class Slider extends View {
|
||||
public void setValue(float value) {
|
||||
if (isValueValid(value)) {
|
||||
thumbPosition = (value - valueFrom) / (valueTo - valueFrom);
|
||||
if (hasOnChangeListener()) {
|
||||
listener.onValueChange(this, getValue());
|
||||
}
|
||||
dispatchOnChanged(false);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
@ -596,21 +607,50 @@ public class Slider extends View {
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the slider has an {@link OnChangeListener} attached, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean hasOnChangeListener() {
|
||||
return listener != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback to be invoked when the slider changes.
|
||||
*
|
||||
* @param listener The callback to run when the slider changes
|
||||
*/
|
||||
public void setOnChangeListener(@Nullable OnChangeListener listener) {
|
||||
this.listener = listener;
|
||||
public void addOnChangeListener(@Nullable OnChangeListener listener) {
|
||||
changeListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback for value changes from this {@link Slider}
|
||||
*
|
||||
* @param listener The callback that'll stop receive slider changes
|
||||
*/
|
||||
public void removeOnChangeListener(@NonNull OnChangeListener listener) {
|
||||
changeListeners.remove(listener);
|
||||
}
|
||||
|
||||
/** Removes all instances of {@link Slider.OnChangeListener} attached to this slider */
|
||||
public void clearOnChangeListeners() {
|
||||
changeListeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback to be invoked when the slider touch event is being started or stopped
|
||||
*
|
||||
* @param listener The callback to run when the slider starts or stops being touched
|
||||
*/
|
||||
public void addOnSliderTouchListener(@NonNull OnSliderTouchListener listener) {
|
||||
touchListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback to be invoked when the slider touch event is being started or stopped
|
||||
*
|
||||
* @param listener The callback that'll stop be notified when the slider is being touched
|
||||
*/
|
||||
public void removeOnSliderTouchListener(@NonNull OnSliderTouchListener listener) {
|
||||
touchListeners.remove(listener);
|
||||
}
|
||||
|
||||
/** Removes all instances of {@link Slider.OnSliderTouchListener} attached to this slider */
|
||||
public void clearOnSliderTouchListeners() {
|
||||
touchListeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1242,9 +1282,8 @@ public class Slider extends View {
|
||||
ensureLabel();
|
||||
updateLabelPosition();
|
||||
invalidate();
|
||||
if (hasOnChangeListener()) {
|
||||
listener.onValueChange(this, getValue());
|
||||
}
|
||||
onStartTrackingTouch();
|
||||
dispatchOnChanged(true);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!thumbIsPressed) {
|
||||
@ -1253,6 +1292,7 @@ public class Slider extends View {
|
||||
return false;
|
||||
}
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
onStartTrackingTouch();
|
||||
}
|
||||
thumbIsPressed = true;
|
||||
thumbPosition = position;
|
||||
@ -1261,15 +1301,14 @@ public class Slider extends View {
|
||||
ensureLabel();
|
||||
updateLabelPosition();
|
||||
invalidate();
|
||||
if (hasOnChangeListener()) {
|
||||
listener.onValueChange(this, getValue());
|
||||
}
|
||||
dispatchOnChanged(true);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
thumbIsPressed = false;
|
||||
thumbPosition = position;
|
||||
snapThumbPosition();
|
||||
ViewUtils.getContentViewOverlay(this).remove(label);
|
||||
onStopTrackingTouch();
|
||||
invalidate();
|
||||
break;
|
||||
default:
|
||||
@ -1347,6 +1386,25 @@ public class Slider extends View {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void dispatchOnChanged(boolean fromUser) {
|
||||
final float value = getValue();
|
||||
for (OnChangeListener listener : changeListeners) {
|
||||
listener.onValueChange(this, value, fromUser);
|
||||
}
|
||||
}
|
||||
|
||||
private void onStartTrackingTouch() {
|
||||
for (OnSliderTouchListener listener : touchListeners) {
|
||||
listener.onStartTrackingTouch(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void onStopTrackingTouch() {
|
||||
for (OnSliderTouchListener listener : touchListeners) {
|
||||
listener.onStopTrackingTouch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
@ -1399,9 +1457,7 @@ public class Slider extends View {
|
||||
if (sliderState.hasFocus) {
|
||||
requestFocus();
|
||||
}
|
||||
if (hasOnChangeListener()) {
|
||||
listener.onValueChange(this, getValue());
|
||||
}
|
||||
dispatchOnChanged(false);
|
||||
}
|
||||
|
||||
static class SliderState extends BaseSavedState {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user