2017-07-27 140 views
2

我有一个很简单的颤振的应用程序与TabBarView两个视图(标签1标签2),它们中的一个(标签1)有许多简单的文本部件一个ListView,这个问题是在我向下滚动的ListView的元素标签1,如果我从标签1标签2,最后我从 标签2刷卡刷卡T ab 1,ListView中的上一个滚动位置Tab 1迷路了。颤振 - ListView的内部上的TabBarView失去其滚动位置

下面是代码:

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)到另一个类? 我的意思是,如果我必须在创建Tab 1和Tab 2时检索数据,我不希望在每次Tab被刷入时都这样做。这会很昂贵。

3.-一般来说,是否有办法防止每次滑动到该选项卡时重新生成选项卡视图(包括它的变量,数据等)?

在此先感谢您。

回答

3

1.-即使我从标签页移动到标签页,我如何保持ListView滚动?

好的,这并不像我想的那么容易,但我想我设法做到了。

我的想法是保持HomePageState中的listview偏移量,当我们滚动listview时,我们只是从通知程序中获得偏移量,并通过setter对其进行设置(请使它更清晰并共享!)。

然后,当我们重建列表视图,我们只是要求我们的主小部件给我们保存的偏移量,通过ScrollController我们初始化与该偏移量列表。

我也改变了你的列表视图,因为它有一个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); 
     } 
     }, 
    ); 
    } 
} 
+0

我真的不知道** ScrollController **,这是我没有阅读文档的错。毫无疑问,你的回答解决了我的问题,非常感谢!顺便说一句,我认为你得到偏移量的方式已经很清晰了。 – SaloGala

+0

我修改了一下你的代码,以便能够在更多的地方使用它,并创建了一个关于它的中型文章 - https://medium.com/@boldijar.paul/flutter-keeping-list-view-index-而变化的页面 - 视图 - c260352f35f8 –

0

是否有执行的Widget构建(BuildContext上下文)方法只有一次的方式...

恕我直言,扑的想法是准备重建始终。它应该很便宜。如果您有一些昂贵的操作,则可以使用State“缓存”结果。例如。你可以在initState做网络请求,并通过setState接收响应时重建。对于选项卡,您可以在父窗口小部件中准备和保存数据。您可以在flutter tutorial中找到关于管理状态的更多信息

+0

其实,图库应用标签演示不保留滚动的列表视图当您从“左”选项卡刷卡为“RIGHT”选项卡,我的Android设备上的Play商店中有最新版本的Flutter Gallery应用程序,并具有相同的问题。你测试过了吗? 关于州政府要“缓存”的结果,我现在将对此进行调查。 非常感谢! – SaloGala

+0

我测试过了,但确实有错误。回去后重叠列表的应用程序栏有问题。 – Mogol