@@ -17,6 +17,26 @@ enum TDStepperEventType { cleanValue }
1717
1818typedef TDStepperOverlimitFunction = void Function (TDStepperOverlimitType type);
1919
20+ /// Stepper控制器
21+ class TDStepperController {
22+ _TDStepperState ? _state;
23+
24+ int _value = 0 ;
25+ int get value => _value;
26+
27+ set value (int value) {
28+ _value = value;
29+ _state? .updateUI ();
30+ }
31+
32+
33+ void _bindState (_TDStepperState _tdStepperState) {
34+ _state = _tdStepperState;
35+ }
36+
37+ }
38+
39+ /// 步进器
2040class TDStepper extends StatefulWidget {
2141 const TDStepper ({
2242 Key ? key,
@@ -34,6 +54,7 @@ class TDStepper extends StatefulWidget {
3454 this .onBlur,
3555 this .onChange,
3656 this .onOverlimit,
57+ this .controller,
3758 }) : super (key: key);
3859
3960 /// 禁用输入框
@@ -61,6 +82,7 @@ class TDStepper extends StatefulWidget {
6182 final TDStepperTheme theme;
6283
6384 /// 值
85+ @Deprecated ('与defaultValue 功能重复,请使用defaultValue或者valueController' )
6486 final int ? value;
6587
6688 /// 默认值
@@ -77,27 +99,36 @@ class TDStepper extends StatefulWidget {
7799
78100 /// 事件控制器
79101 final StreamController <TDStepperEventType >? eventController;
102+
103+ /// Stepper控制器
104+ final TDStepperController ? controller;
80105 @override
81106 State <TDStepper > createState () => _TDStepperState ();
82107}
83108
84109class _TDStepperState extends State <TDStepper > {
85- late int value ;
86- late TextEditingController _controller ;
110+ late TDStepperController _controller ;
111+ late TextEditingController _textController ;
87112 final FocusNode _focusNode = FocusNode ();
88113
89114 @override
90115 void initState () {
91116 super .initState ();
92- value = widget.value ?? widget.defaultValue ?? 0 ;
117+ if (widget.controller != null ) {
118+ _controller = widget.controller! ;
119+ } else {
120+ _controller = TDStepperController ()
121+ ..value = widget.value ?? widget.defaultValue ?? 0 ;
122+ }
123+ _controller._bindState (this );
93124 if (widget.eventController!= null ){
94125 widget.eventController? .stream.listen ((TDStepperEventType event){
95126 if (event == TDStepperEventType .cleanValue){
96127 cleanValue ();
97128 }
98129 });
99130 }
100- _controller = TextEditingController (text: value .toString ());
131+ _textController = TextEditingController (text: _controller._value .toString ());
101132
102133 _focusNode.addListener (() {
103134 if (! _focusNode.hasFocus) {
@@ -110,7 +141,7 @@ class _TDStepperState extends State<TDStepper> {
110141
111142 @override
112143 void dispose () {
113- _controller .dispose ();
144+ _textController .dispose ();
114145 _focusNode.dispose ();
115146 super .dispose ();
116147 }
@@ -133,7 +164,7 @@ class _TDStepperState extends State<TDStepper> {
133164 }
134165
135166 double _getTextWidth () {
136- var textLength = value .toString ().length;
167+ var textLength = _controller._value .toString ().length;
137168 return textLength < 4 ? 0 : (textLength - 4 ) * _getFontSize ();
138169 }
139170
@@ -178,13 +209,13 @@ class _TDStepperState extends State<TDStepper> {
178209 }
179210
180211 void onAdd () {
181- if (value >= widget.max) {
212+ if (_controller._value >= widget.max) {
182213 return ;
183214 }
184215
185- if (value + widget.step > widget.max) {
216+ if (_controller._value + widget.step > widget.max) {
186217 setState (() {
187- value = widget.max;
218+ _controller._value = widget.max;
188219 });
189220
190221 if (widget.onOverlimit != null ) {
@@ -196,20 +227,20 @@ class _TDStepperState extends State<TDStepper> {
196227 }
197228
198229 setState (() {
199- value += widget.step;
230+ _controller._value += widget.step;
200231 });
201232
202233 renderNumber ();
203234 }
204235
205236 void onReduce () {
206- if (value <= widget.min) {
237+ if (_controller._value <= widget.min) {
207238 return ;
208239 }
209240
210- if (value - widget.step < widget.min) {
241+ if (_controller._value - widget.step < widget.min) {
211242 setState (() {
212- value = widget.min;
243+ _controller._value = widget.min;
213244 });
214245
215246 if (widget.onOverlimit != null ) {
@@ -221,31 +252,31 @@ class _TDStepperState extends State<TDStepper> {
221252 }
222253
223254 setState (() {
224- value -= widget.step;
255+ _controller._value -= widget.step;
225256 });
226257 renderNumber ();
227258 }
228259 cleanValue (){
229- value = 0 ;
230- _controller .value = TextEditingValue (
231- text: value .toString (),
260+ _controller._value = 0 ;
261+ _textController .value = TextEditingValue (
262+ text: _controller._value .toString (),
232263 selection: TextSelection .fromPosition (TextPosition (
233264 affinity: TextAffinity .downstream,
234- offset: value .toString ().length,
265+ offset: _controller._value .toString ().length,
235266 )));
236267 _focusNode.unfocus ();
237268 }
238269 void renderNumber () {
239- _controller .value = TextEditingValue (
240- text: value .toString (),
270+ _textController .value = TextEditingValue (
271+ text: _controller._value .toString (),
241272 selection: TextSelection .fromPosition (TextPosition (
242273 affinity: TextAffinity .downstream,
243- offset: value .toString ().length,
274+ offset: _controller._value .toString ().length,
244275 )));
245276 _focusNode.unfocus ();
246277
247278 if (widget.onChange != null ) {
248- widget.onChange !(value );
279+ widget.onChange !(_controller._value );
249280 }
250281 }
251282
@@ -255,7 +286,7 @@ class _TDStepperState extends State<TDStepper> {
255286 children: [
256287 TDStepperIconButton (
257288 type: TDStepperIconType .remove,
258- disabled: widget.disabled || value <= widget.min,
289+ disabled: widget.disabled || _controller._value <= widget.min,
259290 theme: widget.theme,
260291 size: widget.size,
261292 onTap: onReduce,
@@ -287,7 +318,7 @@ class _TDStepperState extends State<TDStepper> {
287318 height: PlatformUtil .isWeb ? _getFontSize () : null ,
288319 padding: const EdgeInsets .symmetric (vertical: 2 ),
289320 child: TextField (
290- controller: _controller ,
321+ controller: _textController ,
291322 enabled: ! widget.disabled && ! widget.disableInput,
292323 focusNode: _focusNode,
293324 style: TextStyle (
@@ -309,7 +340,7 @@ class _TDStepperState extends State<TDStepper> {
309340 try {
310341 if (newValue.text == '' ) {
311342 setState (() {
312- value = widget.min;
343+ _controller._value = widget.min;
313344 });
314345
315346 if (widget.onOverlimit != null ) {
@@ -318,38 +349,38 @@ class _TDStepperState extends State<TDStepper> {
318349 }
319350
320351 return newValue.copyWith (
321- text: value .toString (),
352+ text: _controller._value .toString (),
322353 selection: TextSelection .collapsed (
323- offset: value .toString ().length));
354+ offset: _controller._value .toString ().length));
324355 }
325356
326357 final newNum = int .parse (newValue.text);
327358 if (newNum < widget.min) {
328359 setState (() {
329- value = widget.min;
360+ _controller._value = widget.min;
330361 });
331362 if (widget.onOverlimit != null ) {
332363 widget
333364 .onOverlimit !(TDStepperOverlimitType .minus);
334365 }
335366 } else if (newNum > widget.max) {
336367 setState (() {
337- value = widget.max;
368+ _controller._value = widget.max;
338369 });
339370 if (widget.onOverlimit != null ) {
340371 widget
341372 .onOverlimit !(TDStepperOverlimitType .plus);
342373 }
343374 } else {
344375 setState (() {
345- value = newNum;
376+ _controller._value = newNum;
346377 });
347378 }
348379
349380 return newValue.copyWith (
350- text: value .toString (),
381+ text: _controller._value .toString (),
351382 selection: TextSelection .collapsed (
352- offset: value .toString ().length));
383+ offset: _controller._value .toString ().length));
353384 } catch (e) {
354385 return oldValue;
355386 }
@@ -368,14 +399,25 @@ class _TDStepperState extends State<TDStepper> {
368399 ),
369400 TDStepperIconButton (
370401 type: TDStepperIconType .add,
371- disabled: widget.disabled || value >= widget.max,
402+ disabled: widget.disabled || _controller._value >= widget.max,
372403 theme: widget.theme,
373404 size: widget.size,
374405 onTap: onAdd,
375406 )
376407 ],
377408 );
378409 }
410+
411+ void updateUI () {
412+ if (mounted){
413+ _textController.value = TextEditingValue (
414+ text: _controller._value.toString (),
415+ selection: TextSelection .fromPosition (TextPosition (
416+ affinity: TextAffinity .downstream,
417+ offset: _controller._value.toString ().length,
418+ )));
419+ }
420+ }
379421}
380422
381423typedef TDTapFunction = void Function ();
0 commit comments