我想在点击父选项卡

时间:2019-04-16 14:21:12

标签: dart flutter

想在Flutter中克隆Playstore的首页应用栏滚动功能。 Playstore Appbar我正在尝试制作一个屏幕,其中包含SliverAppBar bottom属性下的静态Tabs。每当我单击任何父静态选项卡时,都需要创建动态选项卡和TabBarViews。我成功完成了,但是遇到了一些问题。

  1. 当我单击任何父选项卡时,我将尝试初始化tabController,但currentIndex仍与上一个父选项卡相同。First Tab Second Tab
  2. 每个选项卡主体必须保存其滚动位置。

这是我的屏幕代码。

class DynamicTabContent {
   IconData icon;
   String tooTip;

   DynamicTabContent.name(this.icon, this.tooTip);
}

int currentTabBlue = 0;

class TestAppHomePage extends StatefulWidget {
 @override
  TestAppHomePageState createState() => new TestAppHomePageState();
}

class TestAppHomePageState extends State<TestAppHomePage>
with TickerProviderStateMixin {
 List<DynamicTabContent> myList = new List();
 ScrollController _scrollController = new ScrollController();
 TabController _tabControllerBlue;
 TabController _tabController;

 handleTabChange() {
    currentTabBlue = _tabControllerBlue.index;
    print("CurrentTab = " + currentTabBlue.toString());
    if (_tabControllerBlue.index == 0) {
      setState(() {
        myList.clear();
        myList.add(new DynamicTabContent.name(Icons.favorite, "Favorited"));
        myList
        .add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));

        this._tabController = new TabController(initialIndex: 0, length: 15, vsync: this);
      });
    } else if (_tabControllerBlue.index == 1) {
      setState(() {
        myList.clear();
        myList.add(new DynamicTabContent.name(Icons.favorite, "Favorited"));
        myList
        .add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));
        myList
        .add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));

        this._tabController = new TabController(initialIndex: 0, length: 15, vsync: this);
      });
    } else if (_tabControllerBlue.index == 2) {
      setState(() {
        myList.clear();
        myList.add(new DynamicTabContent.name(Icons.favorite, "Favorited"));
        myList.add(new DynamicTabContent.name(Icons.favorite, "Favorited"));
        myList
        .add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));
        myList
        .add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));
        myList
        .add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));

        this._tabController = new TabController(initialIndex: 0, length: 15, vsync: this);
      });
    }
  }

  @override
  void initState() {
    print("initState = TestAppHomePage");

    myList.add(new DynamicTabContent.name(Icons.favorite, "Favorited"));
    myList.add(new DynamicTabContent.name(Icons.local_pizza, "local pizza"));

    _tabControllerBlue =
    new TabController(initialIndex: 0, length: 3, vsync: this);
    _tabControllerBlue.addListener(handleTabChange);
    _tabController =
    new TabController(initialIndex: 0, length: myList.length, vsync: this);
  }

  @override
  void dispose() {
    print("dispose");
//    _tabController.removeListener(handleTabChange);
//    _tabController.dispose();
    super.dispose();
  }

  Future<void> executeAfterBuild() async {
    print("Build: Called Back");
  }

  @override
  Widget build(BuildContext context) {
    executeAfterBuild();
    return new Scaffold(
      body: new NestedScrollView(
        controller: _scrollController,
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              leading: IconButton(
                icon: Icon(
                  Icons.arrow_back,
                  color: Colors.white,
                ),
                onPressed: null,
              ),
              title: Text('Kitchen'),
              floating: true,
              pinned: true,
              bottom: TabBar(
                controller: _tabControllerBlue,
                tabs: [
                  Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 1"),
                  Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
                  Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 3"),
                ],
              ),
            ),
            new SliverPersistentHeader(
              pinned: true,
              delegate: TestTabBarDelegate(controller: _tabController),
            ),
          ];
        },
        body: new TestHomePageBody(
          tabController: _tabController,
          scrollController: _scrollController,
          myList: myList,
        ),
      ),
    );
  }
}

class TestHomePageBody extends StatefulWidget {
  TestHomePageBody({this.tabController, this.scrollController, this.myList});

  final TabController tabController;
  final ScrollController scrollController;
  final List<DynamicTabContent> myList;

  State<StatefulWidget> createState() {
    return TestHomePageBodyState();
  }
}

class TestHomePageBodyState extends State<TestHomePageBody> {
  Key _key = new PageStorageKey({});
  bool _innerListIsScrolled = false;

  void _updateScrollPosition() {

    if (!_innerListIsScrolled &&
        widget.scrollController.position.extentAfter == 0.0) {
      setState(() {
        _innerListIsScrolled = true;
       print("_innerListIsScrolled = true");
      });
    } else if (_innerListIsScrolled &&
        widget.scrollController.position.extentAfter > 0.0) {
      setState(() {
        _innerListIsScrolled = false;
        print("_innerListIsScrolled = false");
        // Reset scroll positions of the TabBarView pages
        _key = new PageStorageKey({});
      });
    }
  }

  @override
  void initState() {
    widget.scrollController.addListener(_updateScrollPosition);
    print("initState = TestHomePageBodyState");
    super.initState();
  }

  @override
  void dispose() {
    widget.scrollController.removeListener(_updateScrollPosition);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new TabBarView(
      controller: widget.tabController,
      key: _key,
      children: widget.myList.isEmpty
          ? <Widget>[]
          : widget.myList.map(
              (dynamicContent) {
                return new Card(
                  child: new Column(
                    children: <Widget>[
                      new Container(
                        height: 450.0,
                        width: 300.0,
                        child: new IconButton(
                          icon: new Icon(dynamicContent.icon, size: 100.0),
                          tooltip: dynamicContent.tooTip,
                          onPressed: null,
                        ),
                      ),
                      Text(dynamicContent.tooTip),
                    ],
                  ),
                );
              },
            ).toList(),
    );
  }
}

class TestTabBarDelegate extends SliverPersistentHeaderDelegate {
  TestTabBarDelegate({this.controller});

  final TabController controller;

  @override
  double get minExtent => kToolbarHeight;

  @override
  double get maxExtent => kToolbarHeight;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(
      color: Theme.of(context).cardColor,
      height: kToolbarHeight,
      child: new TabBar(
        controller: controller,
        isScrollable: true,
        labelColor: Theme.of(context).accentColor,
        indicatorSize: TabBarIndicatorSize.label,
        key: new PageStorageKey<Type>(TabBar),
        indicatorColor: Theme.of(context).accentColor,
        tabs: List<Widget>.generate(controller.length, (int index) {
          print(controller.length);
          return new Tab(text: "Excluded Discounted Deals");
        }),
      ),
    );
  }

  @override
  bool shouldRebuild(covariant TestTabBarDelegate oldDelegate) {
    return oldDelegate.controller != controller;
  }
}

1 个答案:

答案 0 :(得分:0)

一种解决方法是使用 PageStorage 。例如。
onTap方法中,您需要编写状态,而在构建窗口小部件时,您需要读取状态,如下所示:

// Reading state:
    var tabInternalIndex = PageStorage.of(context).readState(context, identifier: ValueKey('tab3'));
    _currentTab = tabInternalIndex == null ? _currentTab : tabInternalIndex;

// Writing State
onTap: (int index) {
  setState(() {
    _currentTab = index;
    PageStorage.of(context).writeState(context, index,
        identifier: ValueKey('tab3'));
  });
}

请注意,每个主标签的标识符必须不同。
完整示例:

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: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      initialIndex: 1,
      child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(
            tabs: [
              Tab(icon: Icon(Icons.mail)),
              Tab(icon: Icon(Icons.contacts)),
              Tab(icon: Icon(Icons.info)),
            ],
          ),
          title: Text('Sample tabs'),
        ),
        body: TabBarView(children: <Widget>[
          SubTabs1(),
          SubTabs2(),
          SubTabs3()
        ]),
      ),
    );
  }
}

class SubTabs1 extends StatefulWidget {
  @override
  _SubTabs1State createState() => _SubTabs1State();
}

class _SubTabs1State extends State<SubTabs1> {
  int _currentTab = 0;

  @override
  Widget build(BuildContext context) {
    var tabInternalIndex = PageStorage.of(context)
        .readState(context, identifier: ValueKey('tab1'));
    _currentTab = tabInternalIndex == null ? _currentTab : tabInternalIndex;
    return DefaultTabController(
        initialIndex: _currentTab,
        length: 3,
        child: Scaffold(
            appBar: AppBar(
              bottom: TabBar(
                onTap: (int index) {
                  setState(() {
                    _currentTab = index;
                    PageStorage.of(context).writeState(context, index,
                        identifier: ValueKey('tab1'));
                  });
                },
                tabs: [
                  Tab(icon: Icon(Icons.delete)),
                  Tab(icon: Icon(Icons.delete_forever)),
                  Tab(icon: Icon(Icons.delete_outline)),
                ],
              ),
            ),
            body: TabBarView(
              children: <Widget>[
                Container(
                  color: Colors.green[100],
                  child: Text('Child 5'),
                ),
                Container(
                  color: Colors.green[300],
                  child: Text('Child 6'),
                ),
                Container(
                  color: Colors.green[600],
                  child: Text('Child 7'),
                )
              ],
            )));
  }
}

class SubTabs2 extends StatefulWidget {
  @override
  _SubTabs2State createState() => _SubTabs2State();
}

class _SubTabs2State extends State<SubTabs2> {
  int _currentTab = 0;
  @override
  Widget build(BuildContext context) {
    var tabInternalIndex = PageStorage.of(context)
        .readState(context, identifier: ValueKey('tab2'));
    _currentTab = tabInternalIndex == null ? _currentTab : tabInternalIndex;
    return DefaultTabController(
        initialIndex: _currentTab,
        length: 3,
        child: Scaffold(
            appBar: AppBar(
              bottom: TabBar(
                onTap: (int index) {
                  setState(() {
                    _currentTab = index;
                    PageStorage.of(context).writeState(context, index,
                        identifier: ValueKey('tab2'));
                  });
                },
                tabs: [
                  Tab(icon: Icon(Icons.alarm_add)),
                  Tab(icon: Icon(Icons.alarm_off)),
                  Tab(icon: Icon(Icons.alarm_on)),
                ],
              ),
            ),
            body: TabBarView(
              children: <Widget>[
                Container(
                  color: Colors.yellow[100],
                  child: Text('Child 5'),
                ),
                Container(
                  color: Colors.yellow[300],
                  child: Text('Child 6'),
                ),
                Container(
                  color: Colors.yellow[600],
                  child: Text('Child 7'),
                )
              ],
            )));
  }
}

class SubTabs3 extends StatefulWidget {
  @override
  _SubTabs3State createState() => _SubTabs3State();
}

class _SubTabs3State extends State<SubTabs3> {
  int _currentTab = 0;

  @override
  Widget build(BuildContext context) {
    // Reading state:
    var tabInternalIndex = PageStorage.of(context).readState(context, identifier: ValueKey('tab3'));
    _currentTab = tabInternalIndex == null ? _currentTab : tabInternalIndex;
    return DefaultTabController(
        initialIndex: _currentTab,
        length: 3,
        child: Scaffold(
            appBar: AppBar(
              bottom: TabBar(
                onTap: (int index) {
                  setState(() {
                    _currentTab = index;
                    PageStorage.of(context).writeState(context, index,
                        identifier: ValueKey('tab3'));
                  });
                },
                tabs: [
                  Tab(icon: Icon(Icons.ac_unit)),
                  Tab(icon: Icon(Icons.accessible)),
                  Tab(icon: Icon(Icons.airport_shuttle)),
                ],
              ),
            ),
            body: TabBarView(
              children: <Widget>[
                Container(
                  color: Colors.pink[100],
                  child: Text('Child 1'),
                ),
                Container(
                  color: Colors.pink[300],
                  child: Text('Child 2'),
                ),
                Container(
                  color: Colors.pink[600],
                  child: Text('Child 3'),
                )
              ],
            )));
  }
}

希望获得帮助。