Unverified Commit a276ab3d authored by Anthony's avatar Anthony Committed by GitHub

[Material] Properly call onChangeStart and onChangeEnd in Range Slider (#34869)

Fixes a bug in the Range Sider where the onChangeStart and onChangeEnd were not being called if the initial thumb selection came from a drag (rather than a tap).
parent afe790a7
......@@ -454,8 +454,8 @@ class _RangeSliderState extends State<RangeSlider> with TickerProviderStateMixin
}
// Finds closest thumb. If the thumbs are close to each other, no thumb is
// immediately selected while the drag velocity is zero. If the first
// non-zero velocity is negative, then the left thumb is selected, and if its
// immediately selected while the drag displacement is zero. If the first
// non-zero displacement is negative, then the left thumb is selected, and if its
// positive, then the right thumb is selected.
static final RangeThumbSelector _defaultRangeThumbSelector = (
TextDirection textDirection,
......@@ -463,16 +463,17 @@ class _RangeSliderState extends State<RangeSlider> with TickerProviderStateMixin
double tapValue,
Size thumbSize,
Size trackSize,
double dx, // drag velocity
double dx, // The horizontal delta or displacement of the drag update.
) {
final double touchRadius = math.max(thumbSize.width, RangeSlider._minTouchTargetWidth) / 2;
final bool inStartTouchTarget = (tapValue - values.start).abs() * trackSize.width < touchRadius;
final bool inEndTouchTarget = (tapValue - values.end).abs() * trackSize.width < touchRadius;
// Use the velocity if the thumb touch targets overlap. If dx is 0 and the
// the drag position is in both touch targets, no thumb is selected because
// it is ambiguous to which thumb should be selected. Once the drag
// velocity is non-zero, the thumb selection can be determined.
// Use dx if the thumb touch targets overlap. If dx is 0 and the drag
// position is in both touch targets, no thumb is selected because it is
// ambiguous to which thumb should be selected. If the dx is non-zero, the
// thumb selection is determined by the direction of the dx. The left thumb
// is chosen for negative dx, and the right thumb is chosen for positive dx.
if (inStartTouchTarget && inEndTouchTarget) {
bool towardsStart;
bool towardsEnd;
......@@ -729,6 +730,7 @@ class _RenderRangeSlider extends RenderBox {
HorizontalDragGestureRecognizer _drag;
TapGestureRecognizer _tap;
bool _active = false;
RangeValues _newValues;
bool get isEnabled => onChanged != null;
......@@ -985,11 +987,10 @@ class _RenderRangeSlider extends RenderBox {
// a tap, it consists of a call to onChangeStart with the previous value and
// a call to onChangeEnd with the new value.
final RangeValues currentValues = _discretizeRangeValues(values);
RangeValues newValues;
if (_lastThumbSelection == Thumb.start) {
newValues = RangeValues(tapValue, currentValues.end);
_newValues = RangeValues(tapValue, currentValues.end);
} else if (_lastThumbSelection == Thumb.end) {
newValues = RangeValues(currentValues.start, tapValue);
_newValues = RangeValues(currentValues.start, tapValue);
}
_updateLabelPainter(_lastThumbSelection);
......@@ -997,7 +998,7 @@ class _RenderRangeSlider extends RenderBox {
onChangeStart(currentValues);
}
onChanged(_discretizeRangeValues(newValues));
onChanged(_discretizeRangeValues(_newValues));
_state.overlayController.forward();
if (showValueIndicator) {
......@@ -1017,11 +1018,15 @@ class _RenderRangeSlider extends RenderBox {
void _handleDragUpdate(DragUpdateDetails details) {
final double dragValue = _getValueFromGlobalPosition(details.globalPosition);
// If no selection has been made yet, use the velocity of the drag to
// determine which thumb should be selected.
// If no selection has been made yet, test for thumb selection again now
// that the value of dx can be non-zero. If this is the first selection of
// the interaction, then onChangeStart must be called.
bool shouldCallOnChangeStart = false;
if (_lastThumbSelection == null) {
_lastThumbSelection = sliderTheme.thumbSelector(textDirection, values, dragValue, _thumbSize, size, details.delta.dx);
if (_lastThumbSelection != null) {
shouldCallOnChangeStart = true;
_active = true;
_state.overlayController.forward();
if (showValueIndicator) {
_state.valueIndicatorController.forward();
......@@ -1031,16 +1036,18 @@ class _RenderRangeSlider extends RenderBox {
if (isEnabled && _lastThumbSelection != null) {
final RangeValues currentValues = _discretizeRangeValues(values);
if (onChangeStart != null && shouldCallOnChangeStart) {
onChangeStart(currentValues);
}
final double currentDragValue = _discretize(dragValue);
RangeValues newValues;
final double minThumbSeparationValue = isDiscrete ? 0 : sliderTheme.minThumbSeparation / _trackRect.width;
if (_lastThumbSelection == Thumb.start) {
newValues = RangeValues(math.min(currentDragValue, currentValues.end - minThumbSeparationValue), currentValues.end);
_newValues = RangeValues(math.min(currentDragValue, currentValues.end - minThumbSeparationValue), currentValues.end);
} else if (_lastThumbSelection == Thumb.end) {
newValues = RangeValues(currentValues.start, math.max(currentDragValue, currentValues.start + minThumbSeparationValue));
_newValues = RangeValues(currentValues.start, math.max(currentDragValue, currentValues.start + minThumbSeparationValue));
}
onChanged(newValues);
onChanged(_newValues);
}
}
......@@ -1050,10 +1057,8 @@ class _RenderRangeSlider extends RenderBox {
_state.valueIndicatorController.reverse();
}
if (_active && _state.mounted) {
if (_lastThumbSelection == null)
return;
final RangeValues discreteValues = _discretizeRangeValues(values);
if (_active && _state.mounted && _lastThumbSelection != null) {
final RangeValues discreteValues = _discretizeRangeValues(_newValues);
if (onChangeEnd != null) {
onChangeEnd(discreteValues);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment