一尘不染

Flutter-TabBarView上的ListView失去了滚动位置

flutter

我有一个非常简单的Flutter应用,其 TabBarView 具有两个视图( 选项卡1选项卡2 ),其中一个(
选项卡1 )具有带有许多简单文本小部件的ListView,这是我向下滚动ListView元素后的问题的 标签1 ,如果我刷卡从
标签1标签2 ,最后我刷卡从 标签2选项卡1 ,在ListView控件之前的滚动位置 标签1 迷路。

这是代码:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  TabController controller;

  @override
  void initState() {
    super.initState();
    controller = new TabController(
      length: 2,
      vsync: this,
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var tabs = <Tab>[
      new Tab(icon: new Icon(Icons.home), text: 'Tab 1'),
      new Tab(icon: new Icon(Icons.account_box), text: 'Tab 2')
    ];

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new TabBarView(controller: controller, children: <Widget>[
        new ListView(children: <Widget>[
          new Column(children: <Widget>[
            new Text('Data 1'),
            new Text('Data 2'),
            new Text('Data 3'),
            new Text('Data 4'),
            new Text('Data 5'),
            new Text('Data 6'),
            new Text('Data 7'),
            new Text('Data 8'),
            new Text('Data 9'),
            new Text('Data 10'),
            new Text('Data 11'),
            new Text('Data 12'),
            new Text('Data 13'),
            new Text('Data 14'),
            new Text('Data 15'),
            new Text('Data 16'),
            new Text('Data 17'),
            new Text('Data 18'),
            new Text('Data 19'),
            new Text('Data 20'),
            new Text('Data 21'),
            new Text('Data 22'),
            new Text('Data 23'),
            new Text('Data 24'),
            new Text('Data 25'),
            new Text('Data 26'),
            new Text('Data 27'),
            new Text('Data 28'),
            new Text('Data 29'),
            new Text('Data 30'),
            new Text('Data 31'),
            new Text('Data 32'),
            new Text('Data 33'),
            new Text('Data 34'),
            new Text('Data 35'),
            new Text('Data 36'),
            new Text('Data 37'),
            new Text('Data 38'),
            new Text('Data 39'),
            new Text('Data 40'),
            new Text('Data 41'),
            new Text('Data 42'),
            new Text('Data 43'),
            new Text('Data 44'),
            new Text('Data 45'),
            new Text('Data 46'),
            new Text('Data 47'),
            new Text('Data 48'),
          ])
        ]),
        new Center(child: new Text('Tab 2'))
      ]),
      bottomNavigationBar: new Material(
        color: Colors.deepOrange,
        child: new TabBar(controller: controller, tabs: tabs),
      ),
    );
  }
}

我什至将 TabBarView 子项 (选项卡1和选项卡2)分开放在另一个类中,并且我注意到

@override
  Widget build(BuildContext context) {
  ...
}

每次我滑动到其容器选项卡时,都会执行每个孩子的方法(选项卡1和选项卡2)。

我的问题是:

1.- 即使从一个标签移动到另一个标签,如何保持 ListView 的滚动?

2.-有没有办法执行

@override
Widget build(BuildContext context) {

}

如果我将 TabBarView子项 (选项卡1和选项卡2)分离到另一个类,则仅方法一次?
我的意思是,如果在创建选项卡1和选项卡2时必须检索数据,我不想每次刷入选项卡时都这样做。那会很昂贵。

3.-通常,是否有一种方法可以防止每次我滑动到该选项卡时都重新构建选项卡视图(包括其变量,数据等)?

先感谢您。


阅读 787

收藏
2020-08-13

共1个答案

一尘不染

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

[乔丹·尼尔森的答案]是正确的。不要用我的

如果为每个TabBarView提供一个PageStorageKey,则将保存滚动偏移量。在此处查 看有关PageStorageKey 的更多信息。

👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆

1.-即使从一个标签移动到另一个标签,如何保持ListView的滚动?

好的,这并不像我想的那么容易,但是我认为我做到了。

我的想法是将listview的偏移量保留在HomePageState中,当我们滚动listview时,我们只是从notifier获取偏移量,并通过setter对其进行设置(请使其更加整洁并共享!)。

然后,当我们重建listview时,我们只是要求我们的主窗口小部件给我们保存的偏移量,然后通过ScrollController我们使用该偏移量初始化list。

我还更改了您的listview,因为它具有一个包含50个文本的列元素,以使用50个元素每个包含一个文本。希望你不要介意:)

代码:

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

typedef double GetOffsetMethod();
typedef void SetOffsetMethod(double offset);

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  TabController controller;
  double listViewOffset=0.0;

  @override
  void initState() {
    super.initState();
    controller = new TabController(
      length: 2,
      vsync: this,
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var tabs = <Tab>[
      new Tab(icon: new Icon(Icons.home), text: 'Tab 1'),
      new Tab(icon: new Icon(Icons.account_box), text: 'Tab 2')
    ];

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new TabBarView(
      controller: controller,
      children: <Widget>[
        new StatefulListView(
          getOffsetMethod: () => listViewOffset,
          setOffsetMethod: (offset) => this.listViewOffset = offset,
        ),
        new Center(child: new Text('Tab 2'))
      ]),
      bottomNavigationBar: new Material(
        color: Colors.deepOrange,
        child: new TabBar(controller: controller, tabs: tabs),
      ),
    );
  }
}

class StatefulListView extends StatefulWidget {
  StatefulListView({Key key, this.getOffsetMethod, this.setOffsetMethod}) : super(key: key);

  final GetOffsetMethod getOffsetMethod;
  final SetOffsetMethod setOffsetMethod;

  @override
  _StatefulListViewState createState() => new _StatefulListViewState();
}

class _StatefulListViewState extends State<StatefulListView> {

  ScrollController scrollController;

  @override
  void initState() {
    super.initState();
    scrollController = new ScrollController(
      initialScrollOffset: widget.getOffsetMethod()
    );
  }

  @override
  Widget build(BuildContext context) {
    return new NotificationListener(
      child: new ListView.builder(
        controller: scrollController,
        itemCount: 50,
        itemBuilder: (BuildContext context, int index) {
          return new Text("Data "+index.toString());
        },
      ),
      onNotification: (notification) {
        if (notification is ScrollNotification) {
          widget.setOffsetMethod(notification.metrics.pixels);
        }
      },
    );
  }
}
2020-08-13