【问题标题】:Add SafeArea into SliverAppBar将 SafeArea 添加到 SliverAppBar
【发布时间】:2020-06-18 09:24:24
【问题描述】:

如何使 SliverAppBar 中的 FlexibleSpaceBar 符合 SafeArea?。

CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,
            expandedHeight: 200,
            flexibleSpace: FlexibleSpaceBar(
              collapseMode: CollapseMode.pin,
              title: FittedBox(
                  fit: BoxFit.fitWidth,
                  child: Image.asset('assets/images/user.png')),
            ),
          ),
          SliverList(
            delegate: SliverChildListDelegate([
              TextField(),
            ]),
          )
        ],
      )

我需要图像始终位于 os 标题下方

我尝试用 SafeArea 小部件包装它,但没有成功并崩溃

【问题讨论】:

  • 您是否将您的CustomScrollView 包装成SafeArea
  • @NileshRathod 通过这样做,整个应用栏都被移动了。我只需要移动 FlexibleSpaceBar 的内容
  • 如果我们在SliverAppBar之前使用SliverToBoxAdapter来创建所需的空间呢?
  • @dev-aentgs 嗯.. 没有尝试过.. 不确定这是否会产生预期的效果
  • @delmin 你也用过SafeAreaSliverSafeArea 吗?

标签: flutter dart


【解决方案1】:

以下应该有效:

class TestSafeArea extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverPersistentHeader(
              pinned: true,
              delegate: SafeAreaPersistentHeaderDelegate(
                  expandedHeight: 200,
                  child: Image.asset('assets/YOUR_IMAGE.png'))),
          SliverList(
            delegate: SliverChildListDelegate([
              TextField(),
            ]),
          )
        ],
      ),
    );
  }
}

class SafeAreaPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
  final Widget child;

  final double expandedHeight;

  SafeAreaPersistentHeaderDelegate({this.child, this.expandedHeight});

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return SafeArea(bottom: false, child: SizedBox.expand(child: child));
  }

  @override
  double get maxExtent => expandedHeight;

  @override
  double get minExtent => kToolbarHeight;

  @override
  bool shouldRebuild(SafeAreaPersistentHeaderDelegate old) {
    if (old.child != child) {
      return true;
    }
    return false;
  }
}

很抱歉造成混乱!

【讨论】:

  • 如果您需要为标题添加颜色,只需将安全区域小部件包装在彩色容器中即可:)
  • 我非常感谢您的回答,绝对值得支持。最后一个答案看起来很有希望,但是当向上滚动条子列表时,它会进入 abbbar.. 知道如何解决这个问题吗?
  • 抱歉,“进入 appbar”是什么意思?
  • 如果将 SliverList 的内容滚动到顶部,则该 List 的内容位于 AppBar 上方并一直到屏幕顶部。它应该隐藏在应用栏后面
  • 如果您将 SafeArea 包装在带有颜色的容器中 - 那么列表应该被标题隐藏
【解决方案2】:

编辑 #2 - 刚刚看到您不想将整个 AppBar 放在 SafeArea 中

class SafeAreaPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
  final Widget title;

  final Widget flexibleSpace;

  final double expandedHeight;

  SafeAreaPersistentHeaderDelegate(
      {this.title, this.flexibleSpace, this.expandedHeight});

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    final Widget appBar = FlexibleSpaceBar.createSettings(
      minExtent: minExtent,
      maxExtent: maxExtent,
      currentExtent: max(minExtent, maxExtent - shrinkOffset),
      toolbarOpacity: 1,
      child: AppBar(
        backgroundColor: Colors.blue,
          automaticallyImplyLeading: false,
          title: title,
          flexibleSpace: (title == null && flexibleSpace != null)
              ? Semantics(child: flexibleSpace, header: true)
              : flexibleSpace,
          toolbarOpacity: 1,
          bottomOpacity: 1.0),
    );
    return appBar;
  }

  @override
  double get maxExtent => expandedHeight;

  @override
  double get minExtent => kToolbarHeight;

  @override
  bool shouldRebuild(SafeAreaPersistentHeaderDelegate old) {
    if (old.flexibleSpace != flexibleSpace) {
      return true;
    }
    return false;
  }
}

这将产生您想要的效果。 通过将 SliverPersistentHeader 与自定义 SliverPersistentHeaderDelegate 一起使用,该 SliverPersistentHeaderDelegate 返回包装在 SafeArea 小部件中的 AppBar。

class TestSafeArea extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverPersistentHeader(
            delegate: SafeAreaPersistentHeaderDelegate(
                expandedHeight: 200,
                flexibleSpace: SafeArea(
                  child: Container(
                    color: Colors.red,
                  ),
                )),
          ),
          SliverList(
            delegate: SliverChildListDelegate([
              TextField(),
            ]),
          )
        ],
      ),
    );
  }
}

【讨论】:

  • 我的错 - 我会快速回顾
  • @delmin 请立即查看
  • 嗯...让我试试
  • 在看到您不想移动整个应用栏后稍作更改 - 仅内容,请再看一遍
  • 如果您不想在底部留出空间,请将bottom:false 加入您的安全区。
猜你喜欢
  • 2021-10-20
  • 2020-06-26
  • 2019-05-27
  • 2020-05-06
  • 1970-01-01
  • 2018-12-19
  • 2019-06-20
  • 2022-12-18
  • 2020-11-15
相关资源
最近更新 更多