/
sub_page.dart
140 lines (125 loc) · 3.96 KB
/
sub_page.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import 'package:example/utils/complex_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:smooth/smooth.dart';
class ExamplePageTransitionSubPage extends StatefulWidget {
final bool enableSmooth;
final int listTileCount;
final WidgetWrapper? wrapListTile;
const ExamplePageTransitionSubPage({
super.key,
required this.enableSmooth,
this.listTileCount = 150,
this.wrapListTile,
});
@override
State<ExamplePageTransitionSubPage> createState() =>
_ExamplePageTransitionSubPageState();
}
class _ExamplePageTransitionSubPageState
extends State<ExamplePageTransitionSubPage> {
var tapped = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('First Page')),
body: Builder(
builder: (context) => Center(
child: GestureDetector(
onTap: () => _handleTap(context),
child: Text(
tapped ? 'Tapped, page is loading' : 'Tap me',
style: const TextStyle(fontSize: 18),
),
),
),
),
);
}
void _handleTap(BuildContext context) {
setState(() {
tapped = true;
});
// wait a frame, such that we can tell reader it is tapped
// even for the janky non-smooth case
SchedulerBinding.instance.addPostFrameCallback((_) {
// TODO use our page route
Navigator.push<dynamic>(
context,
_buildPageRoute(
builder: (_) => _SecondPage(
listTileCount: widget.listTileCount,
wrapListTile: widget.wrapListTile,
),
),
);
});
}
PageRoute<dynamic> _buildPageRoute({required WidgetBuilder builder}) {
if (widget.enableSmooth) {
return SmoothMaterialPageRoute<dynamic>(builder: builder);
// // TODO change it to "material" page route
// // currently mimic https://docs.flutter.dev/cookbook/animation/page-route-animation
// return SmoothPageRouteBuilder<dynamic>(
// pageBuilder: (context, _, __) => builder(context),
// transitionsBuilder: (context, animation, secondaryAnimation, child) {
// const begin = Offset(0.0, 1.0);
// const end = Offset.zero;
// const curve = Curves.ease;
//
// final tween =
// Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
//
// return SlideTransition(
// position: animation.drive(tween),
// child: child,
// );
// },
// );
} else {
return MaterialPageRoute<dynamic>(builder: builder);
}
}
}
class _SecondPage extends StatefulWidget {
final int listTileCount;
final WidgetWrapper? wrapListTile;
const _SecondPage({
required this.listTileCount,
required this.wrapListTile,
});
@override
State<_SecondPage> createState() => _SecondPageState();
}
class _SecondPageState extends State<_SecondPage> {
var placeholder = true;
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
// This hack is because [ModalRoute.offstage] needs one extra frame
// to be updated to false. We should find other workarounds later
// so we can remove this extra latency.
// https://github.com/fzyzcjy/flutter_smooth/issues/127#issuecomment-1279972708
SchedulerBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
setState(() => placeholder = false);
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Second Page')),
body: placeholder
// the placeholder to show when the complex widget is loading
? Container(
color: Colors.white,
)
: ComplexWidget(
listTileCount: widget.listTileCount,
wrapListTile: widget.wrapListTile,
),
);
}
}