You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 03:27:04