11import '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' ;
25import 'package:tsdm_client/i18n/strings.g.dart' ;
36import '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