【问题标题】:Sliver AppBar not collapse when using listviewbuilder使用 listviewbuilder 时 Sliver AppBar 不折叠
【发布时间】:2021-12-27 09:08:40
【问题描述】:

我很困惑为什么当我滚动 listviewbuilder 时我的 sliverappbar 没有崩溃

所以我想要的是 Appbar 会折叠,但底部是固定的,当我向上滚动时,appbar 也会显示'n

@override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
              pinned: true,
              snap: true,
              floating: true,
              expandedHeight: 150,
              centerTitle: true,
              title: Text('mama'),
              bottom: AppBar(
                title: Container(
                  height: 45,
                  child: TextField(
                    decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        hintText: 'Enter a search term'),
                  ),
                ),
              ),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    height: MediaQuery.of(context).size.height,
                    child: StreamBuilder<ListsetorModel>(
                        stream: con.resListsetor.stream,
                        builder: (_, snapshot) {
                          if (snapshot.hasData) {
                            if (snapshot.data!.result == null) {
                              return Center(
                                child: Text('Data kosong '),
                              );
                            } else {
                              return Scrollbar(
                                thickness: 5,
                                child: ListView.builder(
                                    itemCount: snapshot.data!.result!.length,
                                    itemBuilder: (context, index) {
                                      var formatDate = DateFormat('yyyy-MM-dd ')
                                          .format(snapshot
                                              .data!.result![index].createdAt!
                                              .toLocal());
                                      Result list =
                                          snapshot.data!.result![index];

                                      return InkWell(
                                        onTap: () {
                                          Navigator.push(
                                              context,
                                              MaterialPageRoute(
                                                  builder: (context) =>
                                                      DetailTransaksi(
                                                          kode: list.kode)));
                                        },
                                        child: Container(
                                          child: Card(
                                            shape: RoundedRectangleBorder(
                                              borderRadius:
                                                  BorderRadius.circular(9.0),
                                            ),
                                            child: Container(
                                              child: Padding(
                                                padding:
                                                    const EdgeInsets.all(20.0),
                                                child: Column(
                                                  mainAxisAlignment:
                                                      MainAxisAlignment.start,
                                                  children: [
                                                    Container(
                                                      child: Row(
                                                        mainAxisAlignment:
                                                            MainAxisAlignment
                                                                .spaceBetween,
                                                        children: [
                                                          Text(
                                                            "Order ${list.kode}",
                                                            style: TextStyle(
                                                                fontWeight:
                                                                    FontWeight
                                                                        .bold),
                                                          ),
                                                          Text(formatDate),
                                                        ],
                                                      ),
                                                    ),
                                                    Divider(),
                                                    Text(
                                                        "Please help us to confirm  \nto get 10% discount code for next order."),
                                                    SizedBox(
                                                      height: 10,
                                                    ),
                                                    Container(
                                                      child: Row(
                                                        mainAxisAlignment:
                                                            MainAxisAlignment
                                                                .spaceBetween,
                                                        children: [
                                                          Container(
                                                            width: 96,
                                                            height: 36,
                                                            color: Color(
                                                                0xff85d057),
                                                            child: TextButton(
                                                              child: Row(
                                                                children: [
                                                                  SizedBox(
                                                                    width: 5,
                                                                  ),
                                                                  Text(
                                                                    "Qr Code",
                                                                    style: TextStyle(
                                                                        color: Colors
                                                                            .white),
                                                                  ),
                                                                  SizedBox(
                                                                    height: 20,
                                                                    width: 20,
                                                                    child: Image
                                                                        .asset(
                                                                            'assets/images/qrscan.png'),
                                                                  )
                                                                ],
                                                              ),
                                                              onPressed: () {
                                                                Navigator.pushReplacement(
                                                                    context,
                                                                    MaterialPageRoute(
                                                                        builder: (context) => Qrcode(
                                                                              data: list.kode!,
                                                                            )));
                                                              },
                                                            ),
                                                          ),
                                                      
                                                          )
                                                        ],
                                                      ),
                                                    ),
                                                  ],
                                                ),
                                              ),
                                            ),
                                          ),
                                        ),
                                      );
                                    }),
                              );
                            }
                          }
                          return Center(child: CircularProgressIndicator());
                        }),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

所以我希望 sliverappbar 在我滚动这个列表视图时崩溃,我尝试在列表视图生成器上添加物理 neverscrollable 它不能正常工作

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    请参考以下代码

    class AnimatedAppBar extends StatefulWidget {
      const AnimatedAppBar({Key key}) : super(key: key);
    
      @override
      _AnimatedAppBarState createState() => _AnimatedAppBarState();
    }
    
    class _AnimatedAppBarState extends State<AnimatedAppBar>
        with TickerProviderStateMixin {
      final TextEditingController stateController = TextEditingController();
      final FocusNode stateFocus = FocusNode();
    
      var animation;
      var controller;
    
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            body: NestedScrollView(
              headerSliverBuilder:
                  (BuildContext context, bool innnerBoxIsScrolled) {
                if (innnerBoxIsScrolled) {
                  /* Animation */
                  controller = AnimationController(
                    vsync: this,
                    duration: Duration(
                      seconds: 1,
                    ),
                  );
                  animation = Tween(
                    begin: 0.0,
                    end: 1.0,
                  ).animate(controller);
                  /* Animation */
                  controller.forward();
                }
                return <Widget>[
                  SliverAppBar(
                    expandedHeight: 120.0,
                    floating: false,
                    pinned: true,
                    backgroundColor: Colors.grey,
                    automaticallyImplyLeading: false,
                    titleSpacing: 0.0,
                    toolbarHeight: 90.0,
                    centerTitle: false,
                    elevation: 0.0,
                    leadingWidth: 0.0,
                    title: Column(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        if (innnerBoxIsScrolled != null &&
                            innnerBoxIsScrolled == true)
                          FadeTransition(
                            opacity: animation,
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.center,
                              children: [
                                SizedBox(
                                  height: 10.0,
                                ),
                                Text(
                                  "Search",
                                  style: TextStyle(
                                    color: Colors.black,
                                  ),
                                ),
                                Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: TextFormField(
                                    autovalidateMode:
                                        AutovalidateMode.onUserInteraction,
                                    /* autovalidate is disabled */
                                    controller: stateController,
                                    inputFormatters: [
                                      FilteringTextInputFormatter.deny(
                                          RegExp(r"\s\s")),
                                      FilteringTextInputFormatter.deny(RegExp(
                                          r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])')),
                                    ],
                                    keyboardType: TextInputType.text,
                                    maxLength: 160,
                                    onChanged: (val) {},
                                    maxLines: 1,
                                    validator: (value) {},
                                    focusNode: stateFocus,
                                    autofocus: false,
                                    decoration: InputDecoration(
                                      errorMaxLines: 3,
                                      counterText: "",
                                      filled: true,
                                      fillColor: Colors.white,
                                      focusedBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Color(0xffE5E5E5),
                                        ),
                                      ),
                                      disabledBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Color(0xffE5E5E5),
                                        ),
                                      ),
                                      enabledBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Color(0xffE5E5E5),
                                        ),
                                      ),
                                      border: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                        ),
                                      ),
                                      errorBorder: OutlineInputBorder(
                                          borderRadius:
                                              BorderRadius.all(Radius.circular(4)),
                                          borderSide: BorderSide(
                                            width: 1,
                                            color: Colors.red,
                                          )),
                                      focusedErrorBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Colors.red,
                                        ),
                                      ),
                                      hintText: "Search" ?? "",
                                    ),
                                  ),
                                ),
                                SizedBox(
                                  height: 6.0,
                                )
                              ],
                            ),
                          ),
                      ],
                    ),
                    // bottom: PreferredSize(
                    //   preferredSize: Size.fromHeight(5.0),
                    //   child: Text(''),
                    // ),
                    flexibleSpace: FlexibleSpaceBar(
                      background: Container(
                        width: MediaQuery.of(context).size.width,
                        child: Stack(
                          alignment: Alignment.center,
                          children: [
                            Column(
                              mainAxisAlignment: MainAxisAlignment.start,
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                SizedBox(
                                  height: 10.0,
                                ),
                                Padding(
                                  padding: EdgeInsets.symmetric(
                                    horizontal: 8.0,
                                  ),
                                  child: Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceBetween,
                                    children: [
                                      Text(
                                        "Search",
                                        style: TextStyle(
                                          fontWeight: FontWeight.bold,
                                          fontSize: 24.0,
                                        ),
                                      ),
                                      CircleAvatar(
                                        backgroundImage: NetworkImage(
                                            "https://images.ctfassets.net/hrltx12pl8hq/2TRIFRwcjrTuNprkTQHVxs/088159eb8e811aaac789c24701d7fdb1/LP_image.jpg?fit=fill&w=632&h=354&fm=webp"), //NetworkImage
                                        radius: 16.0,
                                      ),
                                    ],
                                  ),
                                ),
                                Padding(
                                  padding: const EdgeInsets.all(8.0),
                                  child: TextFormField(
                                    autovalidateMode:
                                        AutovalidateMode.onUserInteraction,
                                    /* autovalidate is disabled */
                                    controller: stateController,
                                    inputFormatters: [
                                      FilteringTextInputFormatter.deny(
                                          RegExp(r"\s\s")),
                                      FilteringTextInputFormatter.deny(RegExp(
                                          r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])')),
                                    ],
                                    keyboardType: TextInputType.text,
                                    maxLength: 160,
                                    onChanged: (val) {},
                                    maxLines: 1,
                                    validator: (value) {},
                                    focusNode: stateFocus,
                                    autofocus: false,
                                    decoration: InputDecoration(
                                      errorMaxLines: 3,
                                      counterText: "",
                                      filled: true,
                                      fillColor: Colors.white,
                                      focusedBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Color(0xffE5E5E5),
                                        ),
                                      ),
                                      disabledBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Color(0xffE5E5E5),
                                        ),
                                      ),
                                      enabledBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Color(0xffE5E5E5),
                                        ),
                                      ),
                                      border: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                        ),
                                      ),
                                      errorBorder: OutlineInputBorder(
                                          borderRadius:
                                              BorderRadius.all(Radius.circular(4)),
                                          borderSide: BorderSide(
                                            width: 1,
                                            color: Colors.red,
                                          )),
                                      focusedErrorBorder: OutlineInputBorder(
                                        borderRadius:
                                            BorderRadius.all(Radius.circular(4)),
                                        borderSide: BorderSide(
                                          width: 1,
                                          color: Colors.red,
                                        ),
                                      ),
                                      hintText: "Search" ?? "",
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                  ),
                ];
              },
              body: Builder(
                builder: (BuildContext context) {
                  return SingleChildScrollView(
                    child: Column(
                      children: [
                        ListView.builder(
                          itemCount: 100,
                          physics: NeverScrollableScrollPhysics(),
                          shrinkWrap: true,
                          itemBuilder: (BuildContext context, int index) {
                            return Padding(
                              padding: const EdgeInsets.all(4.0),
                              child: Text("Index value: $index"),
                            );
                          },
                        )
                      ],
                    ),
                  );
                },
              ),
            ),
          ),
        );
      }
    }
    
    
    

    带有标签栏的嵌套滚动

    
    class NestedScrollWithTabs extends StatefulWidget {
      const NestedScrollWithTabs({Key key}) : super(key: key);
    
      @override
      _NestedScrollWithTabsState createState() => _NestedScrollWithTabsState();
    }
    
    class _NestedScrollWithTabsState extends State<NestedScrollWithTabs>
        with TickerProviderStateMixin {
      
      var animation;
      var controller;
    
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            body: DefaultTabController(
              length: 2,
              child: NestedScrollView(
                physics: NeverScrollableScrollPhysics(),
                headerSliverBuilder: (headerCtx, innnerBoxIsScrolled) {
                  if (innnerBoxIsScrolled) {
                    /* Animation */
                    controller = AnimationController(
                      vsync: this,
                      duration: Duration(
                        seconds: 1,
                      ),
                    );
                    animation = Tween(
                      begin: 0.0,
                      end: 1.0,
                    ).animate(controller);
                    /* Animation */
                    controller.forward();
                  }
    
                  return <Widget>[
                    SliverAppBar(
                      expandedHeight: ScreenUtil().setHeight(185.0),
                      floating: false,
                      pinned: true,
                      backgroundColor: Colors.white,
                      automaticallyImplyLeading: false,
                      titleSpacing: 0.0,
                      centerTitle: true,
                      elevation: 0.0,
                      leadingWidth: 0.0,
                      title: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                        
                          if (innnerBoxIsScrolled != null &&
                              innnerBoxIsScrolled == true)
                            FadeTransition(
                              opacity: animation,
                              child: Text(
                                "Title",
                                style: TextStyle(
                                  color: Colors.black,
                                  fontSize: 22,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                         
                        ],
                      ),
                      flexibleSpace: FlexibleSpaceBar(
                        background: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Stack(
                              alignment: Alignment.center,
                              clipBehavior: Clip.none,
                              children: [
                                Image.network(
                                  "https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
                                      "",
                                  fit: BoxFit.fitWidth,
                                  height: ScreenUtil().setHeight(126.0),
                                  width: ScreenUtil().screenWidth,
                                  filterQuality: FilterQuality.low,
                                  loadingBuilder: (BuildContext context,
                                      Widget child,
                                      ImageChunkEvent loadingProgress) {
                                    if (loadingProgress == null) return child;
                                    return Container(
                                      height: ScreenUtil().setHeight(126.0),
                                      width: ScreenUtil().screenWidth,
                                      color: Colors.grey,
                                    );
                                  },
                                  errorBuilder: (context, error, stackTrace) {
                                    return SizedBox(
                                      height: ScreenUtil().setHeight(126.0),
                                      width: ScreenUtil().screenWidth,
                                      child: Container(
                                        width: ScreenUtil().screenWidth,
                                      ),
                                    );
                                  },
                                ),
                                Positioned(
                                  top: ScreenUtil().setHeight(92.0),
                                  // left: ScreenUtil().setWidth(20.0),
                                  child: Column(
                                    crossAxisAlignment: CrossAxisAlignment.center,
                                    children: [
                                      CircleAvatar(
                                        backgroundColor: Colors.transparent,
                                        radius: 30.0,
                                        child: ClipRRect(
                                          borderRadius: BorderRadius.circular(
                                            45.0,
                                          ),
                                          child: Image.network(
                                            "https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
                                                "",
                                            fit: BoxFit.fill,
                                            height: ScreenUtil().setHeight(72.0),
                                            width: ScreenUtil().screenWidth,
                                            filterQuality: FilterQuality.low,
                                            loadingBuilder: (BuildContext context,
                                                Widget child,
                                                ImageChunkEvent loadingProgress) {
                                              if (loadingProgress == null)
                                                return child;
                                              return Container(
                                                height:
                                                    ScreenUtil().setHeight(72.0),
                                                width: ScreenUtil().screenWidth,
                                                color: Colors.grey,
                                              );
                                            },
                                            errorBuilder:
                                                (context, error, stackTrace) {
                                              return SizedBox(
                                                height:
                                                    ScreenUtil().setHeight(72.0),
                                                width: ScreenUtil().screenWidth,
                                                child: Container(
                                                  width: ScreenUtil().screenWidth,
                                                ),
                                              );
                                            },
                                          ),
                                        ),
                                      ),
                                      Text("Name"),
                                      Text("Place"),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                    SliverOverlapAbsorber(
                      handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
                          headerCtx),
                      sliver: SliverPersistentHeader(
                        delegate: SliverAppBarDelegate(TabBar(
                          labelColor: Colors.blue,
                          unselectedLabelColor: Colors.black,
                          labelStyle: TextStyle(
                            fontSize: 15.0,
                          ),
                          unselectedLabelStyle: TextStyle(
                            fontSize: 15.0,
                          ),
                          labelPadding: EdgeInsets.zero,
                          indicatorColor: Colors.blue,
                          indicatorPadding: EdgeInsets.zero,
                          physics: NeverScrollableScrollPhysics(),
                          tabs: [
                            Tab(
                              text: "Tab 1",
                            ),
                            Tab(
                              text: "Tab 2",
                            ),
                          ],
                        )),
                        pinned: false,
                      ),
                    ),
                  ];
                },
                body: TabBarView(
                  children: [
                    /* Tab 1 */
                    Container(
                      color: Colors.white,
                      child: ListView.builder(
                        itemCount: 100,
                        physics: NeverScrollableScrollPhysics(),
                        shrinkWrap: true,
                        itemBuilder: (BuildContext context, int index) {
                          return Padding(
                            padding: const EdgeInsets.all(4.0),
                            child: Text("Index value: $index"),
                          );
                        },
                      ),
                    ),
                    /* Tab 2 */
                    Container(
                      color: Colors.white,
                      child: ListView.builder(
                        itemCount: 10,
                        physics: NeverScrollableScrollPhysics(),
                        shrinkWrap: true,
                        itemBuilder: (BuildContext context, int index) {
                          return Padding(
                            padding: const EdgeInsets.all(4.0),
                            child: Text("Index value of Tab 2: $index"),
                          );
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        );
      }
    }
    
    class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
      SliverAppBarDelegate(this.tabBars);
    
      final TabBar tabBars;
    
      @override
      double get minExtent => 60.0;
    
      @override
      double get maxExtent => 60.0;
    
      @override
      Widget build(
          BuildContext context, double shrinkOffset, bool overlapsContent) {
        // shinkOffsetPerValue.value = shrinkOffset;
        return new Container(
          color: Colors.white,
          child: Column(
            children: [
              tabBars,
            ],
          ),
        );
      }
    
      @override
      bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
        return false;
      }
    }
    
    
    
    

    【讨论】:

    • 谢谢你的回答,是的,这很完美,但这不是我想要的,所以我在尝试后找到了我的答案
    【解决方案2】:

    所以答案是在 NestedScrollview 中添加

     floatHeaderSlivers: true,
    

    并删除 sliverappbar 内的 snap: true

    【讨论】:

      猜你喜欢
      • 2019-04-21
      • 1970-01-01
      • 2021-07-27
      • 2019-09-07
      • 2019-08-13
      • 1970-01-01
      • 2019-05-03
      • 2020-09-06
      • 1970-01-01
      相关资源
      最近更新 更多