2017-07-27 142 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