如何以编程方式折叠或展开 SliverPresistentHeader [自定义浮动应用栏]

Posted

技术标签:

【中文标题】如何以编程方式折叠或展开 SliverPresistentHeader [自定义浮动应用栏]【英文标题】:How to programmatically Collapse or Expand SliverPresistentHeader [custom floating app bar] 【发布时间】:2021-03-11 13:36:56 【问题描述】:

我正在尝试使用来自shrinkOffset 值的引用以编程方式折叠展开 SliverPresistantHeader。我到处寻找如何实现此功能,但找不到任何解决方案(所以我在这里问)。

这是我的自定义代码 SliverPresistantHeaderDelegate

import 'package:bom/constants/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class BomAppHeader implements SliverPersistentHeaderDelegate 
  BomAppHeader(
    this.expandedHeight,
    this.title,
    this.body,
    @required this.notificationShade,
  );

  final double notificationShade;
  final double expandedHeight;
  final Widget title;
  final Widget body;

  @override
  double get maxExtent 
    if (expandedHeight == null || expandedHeight < kToolbarHeight) 
      return minExtent;
     else 
      return notificationShade + expandedHeight;
    
  

  @override
  double get minExtent 
    return title == null
        ? notificationShade
        : notificationShade + kToolbarHeight;
  

  double bodyOpacity(double shrinkOffset) 
    return max(0.0, 1 - (shrinkOffset / (maxExtent - minExtent)));
  

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) 
    // print(max(0.0, 1 - (shrinkOffset / (maxExtent - minExtent))));

    return Stack(
      fit: StackFit.expand,
      children: [
        Container(
          decoration: kAppBarDecoration,
        ),
        Opacity(
          opacity: bodyOpacity(shrinkOffset),
          child: Container(
            height: maxExtent > minExtent ? double.infinity : 0.0,
            margin: title == null
                ? EdgeInsets.only(top: notificationShade + 2)
                : EdgeInsets.only(
                    top: notificationShade, bottom: kToolbarHeight),
            padding: EdgeInsets.all(8.0),
            child: body,
          ),
        ),
        Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
          SizedBox(
            height: notificationShade,
          ),
          Container(
            height: title == null ? 0.0 : kToolbarHeight,
            padding: EdgeInsets.all(5.0),
            child: title,
          ),
        ]),
      ],
    );
  

  double titleOpacity(double shrinkOffset) 
    // simple formula: fade out text as soon as shrinkOffset > 0
    return 1.0 - max(0.0, shrinkOffset) / maxExtent;
    // more complex formula: starts fading out text when shrinkOffset > minExtent
    //return 1.0 - max(0.0, (shrinkOffset - minExtent)) / (maxExtent - minExtent);
  

  @override
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) 
    return true;
  

  @override
  // TODO: implement showOnScreenConfiguration
  PersistentHeaderShowOnScreenConfiguration get showOnScreenConfiguration =>
      null;

  @override
  // TODO: implement snapConfiguration
  FloatingHeaderSnapConfiguration get snapConfiguration => null;

  @override
  // TODO: implement stretchConfiguration
  OverScrollHeaderStretchConfiguration get stretchConfiguration => null;

  @override
  // TODO: implement vsync
  TickerProvider get vsync => null;

到目前为止,我还没有找到任何解决方案来实现这一点,仍在网上冲浪。

【问题讨论】:

【参考方案1】:

由于 Flutter 是开源的,我们可以访问它们的内置代码(我最近深入研究了每个小部件代码以了解每件事情的工作原理 ;-)),我发现 snap 功能是我最喜欢的功能我正在从颤振文档中寻找。所以我研究了SliverAppBar 以及 snap 是如何在其中实现的。刚刚复制了我需要的东西,现在一切都按预期工作了。

[如果有人需要我的代码,请告诉我。我想没有人对此问题感兴趣或调查过,哈哈,最好说,我的问题是个垃圾问题]

【讨论】:

一点也不,没有愚蠢的问题,我会对你的所作所为和从中取得的成果感兴趣【参考方案2】:

将滚动控制器添加到您的“自定义滚动视图”

ScrollController _scrollController;

Widget build(BuildContext context) 
_scrollController = ScrollController();
return Scaffold(
body: CustomScrollView( shrinkWrap: true, controller: _scrollController,
physics: BouncingScrollPhysics(),
slivers: <Widget>[
SliverAppBar(
pinned: false,
:
:
:
onPressed: () // Scroll to top when on click => Expand 
_scrollController.animateTo(
_scrollController.position.minScrollExtent,
duration:Duration(milliseconds:1300),
curve: Curves.decelerate,);
 ,

onPressed: () // Scroll to bottom when on click => Collapse
scrollController.animateTo(
    scrollController.position.maxScrollExtent,
    duration: Duration(milliseconds: 1300),
    curve: Curves.decelerate,
  );
 ,

【讨论】:

以上是关于如何以编程方式折叠或展开 SliverPresistentHeader [自定义浮动应用栏]的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式折叠或展开 p:accordionPanel

我可以在 Visual Studio 2012 中以编程方式折叠/展开某个名称的所有预处理器块吗?

Swft3 (RxSwift, RxCocoa) - TableView 使用响应式编程展开和折叠概念

Xcode 单击时折叠视图或元素

在 ACE 编辑器中以编程方式折叠代码

winform, ListView Groups 下面的项目如何实现折叠,展开(默认都是展开) 类似treeview的效果