Skip to content

Commit 7f2ae8c

Browse files
authored
Merge pull request #699 from Tencent/feature/zfly_0.2.4
`TDStepper`:Stepper增加controller参数,可用于实时修改value
2 parents 9877c17 + 1489124 commit 7f2ae8c

File tree

2 files changed

+94
-34
lines changed

2 files changed

+94
-34
lines changed

tdesign-component/example/lib/page/td_stepper_page.dart

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ class _TDStepperPageState extends State<TDStepperPage> {
4040
ExampleItem(desc: '步进器样式', builder: _buildStepperWithTheme),
4141
ExampleItem(desc: '步进器尺寸', builder: _buildStepperWithSize)
4242
]),
43-
]),
43+
],
44+
test: [
45+
ExampleItem(desc: '自定义stepValue', builder: _customStepperValue),
46+
],
47+
),
4448
);
4549
}
4650

@@ -114,4 +118,18 @@ class _TDStepperPageState extends State<TDStepperPage> {
114118
),
115119
);
116120
}
121+
122+
var controller = TDStepperController()..value = 1;
123+
@Demo(group: 'stepper')
124+
Widget _customStepperValue(BuildContext context) {
125+
return Row(
126+
mainAxisAlignment: MainAxisAlignment.spaceAround,
127+
children: [
128+
TDStepper(theme: TDStepperTheme.filled, controller: controller,),
129+
TDButton(text: 'value * 2', onTap: (){
130+
controller.value *= 2;
131+
},)
132+
],
133+
);
134+
}
117135
}

tdesign-component/lib/src/components/stepper/td_stepper.dart

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ enum TDStepperEventType { cleanValue }
1717

1818
typedef 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+
/// 步进器
2040
class 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

84109
class _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

381423
typedef TDTapFunction = void Function();

0 commit comments

Comments
 (0)