RefreshIndicator与NestedScrollview。

我想让2个带有ListView的标签页共享一个RefreshIndicator。然而,RefreshIndicator必须有Scrollable作为子节点(TabBarView没有),所以我尝试为每个标签页制作2个RefreshIndicator,如下面的代码所示。

但这带来了一个不同的问题,我还想要一个浮动的AppBar,这意味着我必须使用一个NestedScrollView。所以结果是,每当我向下滚动时,我最终都会触发两个RefreshIndicators的onRefresh方法。而我只需要一个方法来刷新。

import 'package:flutter/material.dart';

main() {
    runApp(
        MaterialApp(
            home: DefaultTabController(
                length: 2,
                child: Scaffold(
                    body: NestedScrollView(
                        headerSliverBuilder: (context, innerBoxIsScrolled) {
                            return [
                                SliverAppBar(
                                    floating: true,
                                    snap: true,
                                    bottom: TabBar(
                                        tabs: [
                                            Tab(text: 'Page1'),
                                            Tab(text: 'Page2'),
                                        ],
                                    ),
                                ),
                            ];
                        },
                        body: TabBarView(
                            children: [
                                Page(1),
                                Page(2),
                            ],
                        ),
                    ),
                ),
            ),
        ),
    );
}

class Page extends StatefulWidget {
    final pageNumber;
    Page(this.pageNumber);
    createState() => PageState();
}

class PageState extends State<Page> with AutomaticKeepAliveClientMixin {
    get wantKeepAlive => true;

    build(context){
        super.build(context);
        return RefreshIndicator(
            onRefresh: () => Future(() async {
                print('Refreshing page no. ${widget.pageNumber}');  // This prints twice once both tabs have been opened
                await Future.delayed(Duration(seconds: 5));
            }),
            child: ListView.builder(
                itemBuilder: ((context, index){
                    return ListTile(
                        title: Text('Item $index')
                    );
                }),
            )
        );
    }
}

AutomaticKeepAliveClientMixin的存在是为了防止每次切换标签页时重建页面,因为这在我的实际应用中是一个昂贵的过程。

最理想的解决方案是为两个标签页使用一个单一的RefreshIndicator,但任何帮助都是感激的。

解决方案:

如果你想要浮动的应用程序栏,那么你必须使用嵌套的滚动视图和sliver应用程序栏。当你尝试在一个列表中使用刷新指示器时,刷新指示器不能工作。这只是因为嵌套的滚动视图。

如果你有两个列表作为标签栏视图的子列表,你想一次只刷新一个或两个,然后按照下面的代码。

用刷新指示器包裹嵌套的滚动视图,然后在刷新部分。

RefreshIndicator(
    color: Colors.red,
    displacement: 70,


    onRefresh: _refreshGeneralList,
    key: _refreshIndicatorKey,
    child: NestedScrollView(


      headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
        return <Widget>[

          SliverAppBar(

            centerTitle: true,
            title: Text(
              "App Bar",
              style: TextStyle(
                  color: Colors.black,
                  fontSize: 14,
            ),
            leading: Padding(
              padding: const EdgeInsets.only(left: 8.0),
              child: IconButton(
                icon: Icon(Icons.profile),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ),
            actions: [
              InkWell(
                  onTap: () {
                    setState(() {
                      isPremium = !isPremium;
                    });
                  },
                  child: Icon(
                    Icons.monetization_on,
                    color: isPremium ? Colors.green : Colors.blueGrey,
                    size: 33,
                  )),
              SizedBox(
                width: 25,
              )
            ],

            elevation: 0,
            backgroundColor: Colors.white,
            pinned: true,
            floating: true,
            forceElevated: innerBoxIsScrolled,
            bottom: isPremium
                ? TabBar(

                labelStyle: TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.w600),
                labelColor: Colors.blueGrey,
                indicatorColor:Colors.red,
                unselectedLabelColor:
                Colors.green,
                labelPadding: EdgeInsets.symmetric(vertical: 13.5),
                controller: _tabController,
                tabs: [
                  Text(
                    "General",
                  ),
                  Text(
                    "Visitors",
                  ),
                ])
                : null,
          )
        ];
      },

      body: isPremium
          ? TabBarView(

          controller: _tabController,
          children: [
        generalNotificationsList(context),
        visitorsNotificationsList(context),
      ])
          : generalNotificationsList(context),
    ),
  ),

添加一个调用未来的函数。在未来的部分,我们将写代码,如果tab栏视图的一个子或两个子将被滚动。

 Future _refreshGeneralList() async{
print('refreshing ');
GeneralNotificationBloc().add(LoadGeneralNotificationEvent(context));
PremiumNotificationBloc().add(LoadPremiumNotificationEvent(context));
return Future.delayed(Duration(seconds: 1));

}

给TA打赏
共{{data.count}}人
人已打赏
解决方案

Rust - trait bound depending on feature?

2022-5-14 10:00:34

解决方案

如何在Cypress中处理Exceptions,与我们在selenium中的处理方式类似。

2022-5-14 10:00:36

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索