Skip to content

Commit

Permalink
feat: support scroll on overflow、input、textarea、sliver by mouse wheel
Browse files Browse the repository at this point in the history
feat: support scroll on overflow、input、textarea、sliver by mouse wheel to #1437 #1435
  • Loading branch information
xuzhongpeng committed Jul 1, 2022
2 parents e1d923d + 935b7ef commit afcd30b
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 6 deletions.
12 changes: 6 additions & 6 deletions kraken/lib/src/css/overflow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import 'package:flutter/animation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:kraken/css.dart';
import 'package:kraken/dom.dart';
Expand Down Expand Up @@ -338,12 +339,11 @@ mixin ElementOverflowMixin on ElementBase {

void _scrollablePointerListener(PointerEvent event) {
if (event is PointerDownEvent) {
if (_scrollableX != null) {
_scrollableX!.handlePointerDown(event);
}
if (_scrollableY != null) {
_scrollableY!.handlePointerDown(event);
}
_scrollableX?.handlePointerDown(event);
_scrollableY?.handlePointerDown(event);
} else if (event is PointerSignalEvent) {
_scrollableX?.handlePinterSignal(event);
_scrollableY?.handlePinterSignal(event);
}
}

Expand Down
15 changes: 15 additions & 0 deletions kraken/lib/src/gesture/scroll_position.dart
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,21 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics {
@override
void jumpTo(double? value);

/// Changes the scrolling position based on a pointer signal from current
/// value to delta without animation and without checking if new value is in
/// range, taking min/max scroll extent into account.
///
/// Any active animation is canceled. If the user is currently scrolling, that
/// action is canceled.
///
/// This method dispatches the start/update/end sequence of scrolling
/// notifications.
///
/// This method is very similar to [jumpTo], but [pointerScroll] will
/// update the [ScrollDirection].
///
void pointerScroll(double delta);

/// Calls [jumpTo] if duration is null or [Duration.zero], otherwise
/// [animateTo] is called.
///
Expand Down
30 changes: 30 additions & 0 deletions kraken/lib/src/gesture/scroll_position_with_single_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:math' as math;

import 'package:flutter/animation.dart';
import 'package:flutter/gestures.dart';
Expand Down Expand Up @@ -148,6 +149,16 @@ class ScrollPositionWithSingleContext extends ScrollPosition implements ScrollAc
ScrollDirection get userScrollDirection => _userScrollDirection;
ScrollDirection _userScrollDirection = ScrollDirection.idle;

/// Set [userScrollDirection] to the given value.
///
/// If this changes the value, then a [UserScrollNotification] is dispatched.
void updateUserScrollDirection(ScrollDirection value) {
assert(value != null);
if (userScrollDirection == value)
return;
_userScrollDirection = value;
}

@override
Future<void> animateTo(
double? to, {
Expand Down Expand Up @@ -182,6 +193,25 @@ class ScrollPositionWithSingleContext extends ScrollPosition implements ScrollAc
goBallistic(0.0);
}

@override
void pointerScroll(double delta) {
assert(delta != 0.0);

final double targetPixels =
math.min(math.max(pixels + delta, minScrollExtent), maxScrollExtent);
if (targetPixels != pixels) {
goIdle();
updateUserScrollDirection(
-delta > 0.0 ? ScrollDirection.forward : ScrollDirection.reverse,
);
final double oldPixels = pixels;
forcePixels(targetPixels);
isScrollingNotifier.value = true;
notifyListeners();
goBallistic(0.0);
}
}

@Deprecated(
'This will lead to bugs.') // ignore: flutter_deprecation_syntax, https://github.com/flutter/flutter/issues/44609
@override
Expand Down
45 changes: 45 additions & 0 deletions kraken/lib/src/gesture/scrollable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import 'package:flutter/gestures.dart';
import 'dart:math' as math;
import 'package:flutter/physics.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
Expand Down Expand Up @@ -77,6 +78,10 @@ class KrakenScrollable with _CustomTickerProviderStateMixin implements ScrollCon
}
}

void handlePinterSignal(PointerSignalEvent event) {
_receivedPointerSignal(event);
}

@override
AxisDirection get axisDirection => _axisDirection;

Expand Down Expand Up @@ -205,6 +210,46 @@ class KrakenScrollable with _CustomTickerProviderStateMixin implements ScrollCon
_drag?.update(details);
}

void _receivedPointerSignal(PointerSignalEvent event) {
if (event is PointerScrollEvent && position != null) {
if (_physics != null && !_physics.shouldAcceptUserOffset(position!)) {
return;
}
final double delta = _pointerSignalEventDelta(event);
final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta);
// Only express interest in the event if it would actually result in a scroll.
if (delta != 0.0 && targetScrollOffset != position?.pixels) {
GestureBinding.instance!.pointerSignalResolver.register(event, _handlePointerScroll);
}
}
}
double _pointerSignalEventDelta(PointerScrollEvent event) {
double delta = axis == Axis.horizontal
? event.scrollDelta.dx
: event.scrollDelta.dy;

if (axisDirectionIsReversed(axisDirection)) {
delta *= -1;
}
return delta;
}

double _targetScrollOffsetForPointerScroll(double delta) {
return math.min(
math.max(position!.pixels + delta, position!.minScrollExtent),
position!.maxScrollExtent,
);
}

void _handlePointerScroll(PointerSignalEvent event) {
assert(event is PointerScrollEvent);
final double delta = _pointerSignalEventDelta(event as PointerScrollEvent);
final double targetScrollOffset = _targetScrollOffsetForPointerScroll(delta);
if (delta != 0.0 && targetScrollOffset != position!.pixels) {
position!.pointerScroll(delta);
}
}

void _handleDragEnd(DragEndDetails details) {
// _drag might be null if the drag activity ended and called _disposeDrag.
assert(_hold == null || _drag == null);
Expand Down
3 changes: 3 additions & 0 deletions kraken/lib/src/rendering/sliver_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:kraken/css.dart';
import 'package:kraken/gesture.dart';
Expand Down Expand Up @@ -124,6 +125,8 @@ class RenderSliverListLayout extends RenderLayoutBox {
void _scrollablePointerListener(PointerEvent event) {
if (event is PointerDownEvent) {
scrollable.handlePointerDown(event);
} else if (event is PointerSignalEvent) {
scrollable.handlePinterSignal(event);
}
}

Expand Down
3 changes: 3 additions & 0 deletions kraken/lib/src/rendering/text_control.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import 'dart:math' as math;
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:kraken/css.dart';
import 'package:kraken/dom.dart';
Expand All @@ -26,6 +27,8 @@ class RenderTextControlLeaderLayer extends RenderLeaderLayer {
void _pointerListener(PointerEvent event) {
if (event is PointerDownEvent) {
scrollable.handlePointerDown(event);
} else if (event is PointerSignalEvent) {
scrollable.handlePinterSignal(event);
}
}

Expand Down

0 comments on commit afcd30b

Please sign in to comment.