Flutter Slider编程更新值后无法拖动问题咨询
Flutter Slider 无法拖动异常解决
问题表现
开发中实现编辑流记录页面时,Slider初始值可正常展示,但无法拖动滑块,同页面的自定义输入框StyledInput更新逻辑无异常。
实现逻辑为页面构建时,通过_initFlowRecordFromRoute方法读取ModalRoute.of(context).settings.arguments传入的FlowRecord参数,调用setState更新表单全量数据。
问题代码
页面组件代码
import 'package:flutter/material.dart'; import '../models/flow_record.dart'; import '../consts/consts.dart'; import '../widgets/styled_input.dart'; import '../services/db_self_improve_servicce.dart'; class EditFlowRecordScreen extends StatefulWidget { static const String routeName = '/editFlowrecord'; @override _EditFlowRecordScreenState createState() => _EditFlowRecordScreenState(); } class _EditFlowRecordScreenState extends State<EditFlowRecordScreen> { final _formKey = GlobalKey<FormState>(); final _text1 = TextEditingController(); final _text2 = TextEditingController(); final _text3 = TextEditingController(); final _values = [50.0, 50.0, 50.0]; FlowRecord _flowRecor; void _initFlowRecordFromRoute() { _flowRecor = ModalRoute.of(context).settings.arguments as FlowRecord; setState(() { _text1.text = _flowRecor.record1; _text2.text = _flowRecor.record2; _text3.text = _flowRecor.record3; _values[0] = _flowRecor.record1val > 0 ? _flowRecor.record1val : 0; _values[1] = _flowRecor.record2val > 0 ? _flowRecor.record2val : 0; _values[2] = _flowRecor.record3val > 0 ? _flowRecor.record3val : 0; }); } Widget _buildTextAreaWithRatioForm( TextEditingController text, int valueIndex, ) { return Padding( padding: const EdgeInsets.only(bottom: 8, left: 8, right: 8), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ StyledInput( label: 'Happy thing ${valueIndex + 1}', controller: text, color: SelfImpruveConsts.mainColor, validator: (value) => null, minLine: 2, maxLine: 30, ), SizedBox( height: 20, ), Slider.adaptive( value: _values[valueIndex], min: 0, max: 100, divisions: 100, activeColor: SelfImpruveConsts.mainColor, label: _values[valueIndex].round().toString(), onChanged: (double value) { setState(() { _values[valueIndex] = value; }); }, ) ], ), ); } void _submit() { _flowRecor.record1 = _text1.text; _flowRecor.record2 = _text2.text; _flowRecor.record3 = _text3.text; _flowRecor.record1val = _values[0]; _flowRecor.record2val = _values[1]; _flowRecor.record3val = _values[2]; DbSelfImproveService.editFlowRecord(_flowRecor); return Navigator.pop(context); } @override Widget build(BuildContext context) { _initFlowRecordFromRoute(); return Scaffold( appBar: AppBar( title: Text('Edit Flow Record'), actions: [ IconButton( onPressed: _submit, icon: Icon(Icons.save_outlined), ), ], ), body: Padding( padding: EdgeInsets.symmetric(vertical: 0, horizontal: 10), child: Form( key: _formKey, child: SingleChildScrollView( child: Column( children: [ _buildTextAreaWithRatioForm(_text1, 0), _buildTextAreaWithRatioForm(_text2, 1), _buildTextAreaWithRatioForm(_text3, 2), ], ), ), ), ), ); } }
FlowRecord 模型代码
class FlowRecord { final String id; String record1; double record1val; String record2; double record2val; String record3; double record3val; final DateTime created; final String createdBy; FlowRecord({ this.id, this.record1, this.record1val, this.record2, this.record2val, this.record3, this.record3val, this.createdBy, this.created, }); factory FlowRecord.fromFirestore(DocumentSnapshot doc) { Map data = doc.data(); return FlowRecord( id: doc.id, created: data['created'] != null ? DateTime.fromMillisecondsSinceEpoch(data['created']) : null, createdBy: data['createdBy'], record1: data['record1'], record2: data['record2'], record3: data['record3'], record1val: data['record1val'], record2val: data['record2val'], record3val: data['record3val'], ); } }
根因定位
_initFlowRecordFromRoute初始化方法被放在了build函数中执行,每次组件触发重绘(包括拖动Slider调用setState后),都会重新从路由参数读取初始值覆盖当前的Slider值,导致滑块看起来被“卡住”无法拖动。
修复方案
- 移除
build方法中的_initFlowRecordFromRoute调用 - 将初始化逻辑迁移至
initState生命周期,保证仅在页面首次加载时执行一次赋值
调整后代码示例:
@override void initState() { super.initState(); // 等待组件挂载完成后读取路由参数 WidgetsBinding.instance.addPostFrameCallback((_) { _initFlowRecordFromRoute(); }); } @override Widget build(BuildContext context) { // 此处删除原有的_initFlowRecordFromRoute()调用 return Scaffold( // 原有页面布局逻辑保持不变 ); }
如果页面存在路由参数变更的场景,可额外配合didUpdateWidget生命周期做差异化判断,常规编辑页场景以上修改即可解决问题。
内容的提问来源于stack exchange,提问作者Miroslav Peterka
相关产品推荐
相关产品推荐

