Skip to content

Commit bffe109

Browse files
committed
feat(jump_page): optimize jump page dialog
No more janking, much more intuitive.
1 parent 638b7fc commit bffe109

File tree

1 file changed

+74
-25
lines changed

1 file changed

+74
-25
lines changed
Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
3+
import 'package:go_router/go_router.dart';
4+
import 'package:tsdm_client/constants/layout.dart';
25
import 'package:tsdm_client/i18n/strings.g.dart';
36
import 'package:tsdm_client/widgets/custom_alert_dialog.dart';
47

58
/// A dialog to ask jump page info from user before jump page.
6-
class JumpPageDialog extends StatelessWidget {
9+
class JumpPageDialog extends StatefulWidget {
710
/// Constructor.
811
const JumpPageDialog({required this.current, required this.max, this.min = 0, super.key})
912
: assert(max >= min, 'max index should be not less than min'),
@@ -20,36 +23,82 @@ class JumpPageDialog extends StatelessWidget {
2023
/// Maximum page number.
2124
final int max;
2225

26+
@override
27+
State<JumpPageDialog> createState() => _JumpPageDialogState();
28+
}
29+
30+
class _JumpPageDialogState extends State<JumpPageDialog> {
31+
late int currentPage;
32+
late final TextEditingController textController;
33+
34+
@override
35+
void initState() {
36+
super.initState();
37+
currentPage = widget.current;
38+
textController = TextEditingController(text: '$currentPage');
39+
}
40+
41+
@override
42+
void dispose() {
43+
super.dispose();
44+
textController.dispose();
45+
}
46+
2347
@override
2448
Widget build(BuildContext context) {
25-
var v = current;
26-
final choicesList = List.generate(max - min + 1, (index) {
27-
return min + index;
28-
}).toList();
2949
return CustomAlertDialog.sync(
3050
title: Text(context.t.jumpDialog.title),
31-
// FIXME: Here should handle better when both large mount or small mount
32-
// of choices.
33-
// Issue is that Column will junk is choices are too many and ListView
34-
// fills all height even there are only few choices.
3551
content: Column(
36-
children: choicesList
37-
.map(
38-
(e) => RadioListTile(
39-
title: Text('$e'),
40-
value: e,
41-
groupValue: v,
42-
onChanged: (value) {
43-
if (value == null) {
44-
return;
45-
}
46-
v = value;
47-
Navigator.pop(context, v);
48-
},
49-
),
50-
)
51-
.toList(),
52+
children: [
53+
Slider(
54+
autofocus: true,
55+
// Since flutter 3.29
56+
// ignore: deprecated_member_use
57+
year2023: false,
58+
max: widget.max.toDouble(),
59+
min: widget.min.toDouble(),
60+
divisions: widget.max - 1,
61+
label: '$currentPage',
62+
value: currentPage.toDouble(),
63+
onChanged: (v) => setState(() {
64+
currentPage = v.round();
65+
textController.text = currentPage.toString();
66+
}),
67+
),
68+
sizedBoxW12H12,
69+
TextField(
70+
controller: textController,
71+
decoration: const InputDecoration(
72+
border: UnderlineInputBorder(),
73+
constraints: BoxConstraints(maxWidth: 100),
74+
),
75+
textAlign: TextAlign.center,
76+
inputFormatters: [FilteringTextInputFormatter(RegExp(r'\d'), allow: true)],
77+
keyboardType: TextInputType.number,
78+
onChanged: (v) {
79+
final vv = int.tryParse(v);
80+
if (vv == null || vv < widget.min || vv > widget.max) {
81+
return;
82+
}
83+
setState(() => currentPage = vv);
84+
},
85+
),
86+
],
5287
),
88+
actions: [
89+
TextButton(child: Text(context.t.general.cancel), onPressed: () => context.pop()),
90+
TextButton(
91+
child: Text(context.t.general.ok),
92+
onPressed: () {
93+
if (currentPage != widget.current) {
94+
// Page changed.
95+
context.pop(currentPage);
96+
} else {
97+
context.pop();
98+
}
99+
},
100+
),
101+
],
53102
);
54103
}
55104
}

0 commit comments

Comments
 (0)