Flutter — обновить ListView и сбросить положение прокрутки

У меня есть ListView, где я меняю элементы в списке, нажав кнопку. Теперь проблема в том, что когда я прокручиваю вниз до конца списка, а затем нажимаю кнопку, элементы меняются, но положение списка остается прежним (поэтому, когда я прокручивал вниз и элемент № 2 моего предыдущего списка был в вверху, то пункт №2 нового списка тоже будет вверху). Я хочу, чтобы список снова начинался сверху, и мне снова приходилось прокручивать вниз.

мой основной.дротик:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List _list;
  List _list1 = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6'];
  List _list2 = ['Element A', 'Element B', 'Element C', 'Element D', 'Element E', 'Element F'];
  bool _isList1;

  @override
  void initState() {
    _list = _list1;
    _isList1 = true;
    super.initState();
  }

  void _changeList() {
    setState(() {
      if (_isList1) {
        _list = _list2;
        _isList1 = false;
      } else {
        _list = _list1;
        _isList1 = true;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Schürer',
        home: Scaffold(
          appBar: AppBar(
            title: Text('ListView'),
          ),
          body: Column(
            children: <Widget>[
              RaisedButton(
                child: Text("Change List"),
                onPressed: _changeList,
              ),
              Expanded(
                child: ListView(
                  children: _list
                      .map(
                        (item) => Card(
                              child: Container(
                                padding: EdgeInsets.all(50),
                                color: Colors.black26,
                                child: Text(item),
                              ),
                            ),
                      )
                      .toList(),
                ),
              ),
            ],
          ),
        ));
  }
}
7
0
13 457
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

здесь вы должны указать ключ для Посмотреть список, чтобы различать два разных списка. если вы не предоставляете ключ, то флаттер думает, что оба являются одним и тем же представлением списка, и продолжает отслеживать список, используя его индекс.

какое может быть решение в вашем случае, если мы рассматриваем первый элемент списка как ключ.

....
child: ListView(
              key: ObjectKey(_list[0]),
              children: _list
.....

если вы удовлетворены ответом, примите и проголосуйте за ответ сообщества.

Viren V Varasadiya 17.04.2019 18:49

спасибо, это сработало. Для моего другого варианта использования мне пришлось добавить ScrollController с keepScrollOffset: false, поэтому мой ListView теперь имеет key: ObjectKey(_list.hashCode), и controller: ScrollController(keepScrollOffset: false),

testingFlutter 17.04.2019 18:50

Работал отлично! У меня был поставщик, который я использую в качестве фильтра в списке, и я установил свойство активного отфильтрованного списка как ключ («свойство») в ListViewBuilder, поэтому немного отличается.

Alex Rindone 13.07.2020 04:08

Эта техника работала для меня:

создайте переменную ScrollController:

ScrollController _scrollController = ScrollController();
...
...
_scrollController.animateTo(0, duration: Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);

Это описание animateTo() от порхать:

Animates the position from its current value to the given value.

Я вызывал эту функцию всякий раз, когда значение textfield изменялось.

С контроллером прокрутки вы можете сделать следующее, что приведет вас к началу вашего ListView:

ScrollController _scrollController = ScrollController();
...
...
_scrollController.jumpTo(0);

Конечно, вы можете изменить индекс с 0 на любой индекс ListTile, чтобы перейти к любому элементу ListTile, который вы хотите в своем ListView.

Другие вопросы по теме