我有一个非常简单的Ffltter应用程序,TabBarView有两个视图(Tab 1Tab 2),其中一个(Tab 1)有一个包含许多简单文本小部件的ListView,问题是在我向下滚动Tab 1的ListView元素后,如果我从Tab 1滑动到Tab 2,最后从 Tab 2Tab 1,ListView中Tab 1的上一个滚动位置丢失.

以下是代码:

import 'package:flutter/material.dart';

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

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

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

  final String title;

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

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

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

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

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

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: TabBarView(controller: controller, children: <Widget>[
        ListView(children: <Widget>[
          Column(children: <Widget>[
            for (int i = 0; i < 48; i++) Text('Data $i'),
          ])
        ]),
        const Center(child: Text('Tab 2'))
      ]),
      bottomNavigationBar: Material(
        color: Colors.deepOrange,
        child: TabBar(controller: controller, tabs: tabs),
      ),
    );
  }
}

我甚至在另一个类中将TabBarViewchildrens(表1和表2)分开,我注意到

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

方法(Tab 1和Tab 2),每次我滑动到它的容器选项卡时都会执行.

我的问题是:

1.- How can I keep the scroll of the ListView even if I move from tab to tab?

2.- Is there a way to execute the

@override
Widget build(BuildContext context) {

}

method only once if I separate the TabBarView childrens (Tab 1 and Tab 2) to another classes?个 我的意思是,如果我必须在创建Tab 1和Tab 2时检索数据,我不想在每次滑动Tab时都这样做.那会很贵的.

3.- In general, Is there a way to prevent that a tab view (including it's variables, data, etc.) be rebuilt every time I swipe to that tab?

Thank you in advance.

推荐答案

???????????????

Jordan Nelson's answer是正确的.别用我的.

?

1.- How can I keep the scroll of the ListView even if I move from tab to tab?

好吧,这并不像我想的那么容易,但我想我做到了.

我的 idea 是将listview的偏移量保留在HomePageState中,当我们滚动listview时,我们只是从通知程序获得偏移量,并通过setter设置它(请使它更干净并共享!)

然后,当我们重建listview时,我们只需要让主小部件给我们保存的偏移量,然后通过ScrollController,我们用该偏移量初始化列表.

我还更改了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);
        }
      },
    );
  }
}

Flutter相关问答推荐

如何在容器中移动图标按钮?

关闭视频通话,相机仍在运行!(Flutter WebRTC)

为什么我需要等待重新访问Firestore数据库,即使它已经做了之前?

在创建肘部并使用冻结时,无法使用中的Copy With方法

Flutter -如何停止块监听程序在后台堆栈中运行

如何在Ffltter Chrome应用程序中使用webview_fltter_web显示自定义html而不是外部uri?

'Flutter的无效常数值错误

脚本具有不受支持的MIME类型(';Text/html';).(messaging/failed-service-worker-registration)

我怎样才能在Ffltter中显示html布局链接?

通过Ffltter应用程序与Docker服务器进行交互以进行身份验证

如何使listview.builder在筛选列表后实时更新

创建仅定义导出的文件是否有意义?

使用 Riverpod 和 copyWith 方法更新数据类中列表中变量的值

Flutter/Dart - 从外部类更新状态

按下 Command+W 时关闭窗口

通过点击缩略图加载全屏图像

String类型不是Widget类型的子类型?在dart 中

Flutter - 检测手指何时进入容器

setState 不会在第一次更新 - Flutter

Flutter - 如何调用此函数?