-
Notifications
You must be signed in to change notification settings - Fork 72
/
Copy pathnotification_handler.dart
89 lines (69 loc) · 2.25 KB
/
notification_handler.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_momo_ui/debounce.dart';
class CollapsingNotification extends Notification {
final double transformValue;
CollapsingNotification(this.transformValue);
}
class AppBarScrollHandler extends StatefulWidget {
const AppBarScrollHandler({
super.key,
required this.minExtent,
required this.maxExtent,
required this.controller,
required this.child,
});
final double minExtent;
final double maxExtent;
final ScrollController controller;
final Widget child;
@override
State<AppBarScrollHandler> createState() => _AppBarScrollHandlerState();
}
class _AppBarScrollHandlerState extends State<AppBarScrollHandler> {
double t = 0;
ScrollDirection? scrollDirection;
final Debounce debounce = Debounce(ms: 300);
@override
void dispose() {
debounce.dispose();
super.dispose();
}
void animateTo(double offset) {
widget.controller.animateTo(offset, duration: const Duration(milliseconds: 500), curve: Curves.ease);
}
void reverseDirectionHandler() {
if (t >= 0.15) return animateTo(widget.maxExtent - widget.minExtent);
animateTo(0);
}
void forwardDirectionHandler() {
if (t <= 0.85) return animateTo(0);
animateTo(widget.minExtent);
}
void scrollDirectionHandler() {
if (scrollDirection == ScrollDirection.reverse) reverseDirectionHandler();
if (scrollDirection == ScrollDirection.forward) forwardDirectionHandler();
scrollDirection = null;
}
@override
Widget build(BuildContext context) {
return NotificationListener(
onNotification: (notification) {
if (notification is CollapsingNotification) {
t = notification.transformValue;
}
if (notification is ScrollUpdateNotification) {
final scrollDelta = notification.scrollDelta;
if (scrollDelta == null) return false;
scrollDirection = scrollDelta > 0 ? ScrollDirection.reverse : ScrollDirection.forward;
}
if (notification is ScrollEndNotification) {
if (t == 0 || t == 1 || scrollDirection == null) return false;
debounce.run(scrollDirectionHandler);
}
return false;
},
child: widget.child,
);
}
}