首页 > 解决方案 > Flutter:调用setState时ListView滚动回原点

问题描述

我有一个带有一堆图标的水平 ListView。当用户单击图标时,我会调用setState以跟踪所选项目的索引(因此我可以突出显示它)。

问题是,无论何时选择一个项目,ListView 都会滚动回到开头(参见下面的 GIF):

单击时 ListView 重置位置

这是代码:

class _FormScreenState extends State<FormScreen> {
  int selectedCategory = 0;
  final categories = [
    {'icon': Icons.shopping_basket, 'category': 'Shopping'},
    {'icon': Icons.local_cafe, 'category': 'Eating out'},
    // ....
  ];

  Widget build(BuildContext context) {
    final _formKey = GlobalKey<FormState>();

    return Form(
      key: _formKey,
      child: SafeArea(
        child: Container(
          margin: EdgeInsets.symmetric(horizontal: 10.0),
          child: Column(
            children: <Widget>[
              SizedBox(height: 40.0),
              Text('Some money disappeared ',
                  style: TextStyle(fontSize: 24.0)),
              SizedBox(height: 40.0),
              TextFormField(
                autofocus: true,
                controller: _ctrlTxtAmount,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(
                  hintText: 'AED ...',
                ),
                focusNode: fcsNodeTxtAmount,
                style: TextStyle(fontSize: 22),
                validator: (value) {
                  if (value.isEmpty || double.tryParse(value) == null) {
                    return "Amount needs to be a number";
                  }

                  return null;
                },
              ),
              SizedBox(height: 30.0),
              Container(
                height: 70.0,
                child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: categories.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                        padding: const EdgeInsets.all(12.0),
                        child: GestureDetector(
                          onTap: () {
                            setState(() {
                              selectedCategory = index;
                            });
                          },
                          child: Icon(categories[index]['icon'],
                              size: 40.0,
                              color: selectedCategory == index
                                  ? Colors.purple
                                  : Colors.grey),
                        ));
                  },
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              TextField(
                controller: _ctrlTxtDescription,
                decoration: InputDecoration(
                  hintText: 'What was it for?',
                ),
                style: TextStyle(fontSize: 22),
              ),
              SizedBox(
                height: 20.0,
              ),
              FlatButton(
                  onPressed: () {
                    if (_formKey.currentState.validate()) {
                      Scaffold.of(context).showSnackBar(SnackBar(
                          content: Text(
                        'Hang on a sec..',
                        style: TextStyle(fontSize: 22),
                      )));

                      // Submit to server
                      _submitGoogleForm().then((isSuccess) {
                        // Report result
                        Scaffold.of(context).showSnackBar(SnackBar(
                            content: Text(
                          isSuccess ? 'Success' : 'Failed',
                          style: TextStyle(fontSize: 22),
                        )));

                        // Hide Snackbar in use (if present)
                        Scaffold.of(context).hideCurrentSnackBar();

                        if (isSuccess) {
                          _clearForm();

                          // Focus on Amount
                          FocusScope.of(context).requestFocus(fcsNodeTxtAmount);
                        }
                      });
                    }
                  },
                  color: Colors.purple,
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      'Log it',
                      style: TextStyle(fontSize: 22.0, color: Colors.white),
                    ),
                  ))
            ],
          ),
        ),
      ),
    );
  }
}

如何防止它向后滚动?

我试过了:

标签: flutter

解决方案


final _formKey = GlobalKey<FormState>();从方法中删除build并将其作为状态变量。

class _FormScreenState extends State<FormScreen> {
  final _formKey = GlobalKey<FormState>();
  ...

  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: SafeArea(
        child: Container(
        ...

推荐阅读