Добавить SafeArea в SliverAppBar - PullRequest
1 голос
/ 18 июня 2020

Как сделать, чтобы FlexibleSpaceBar в SliverAppBar уважал 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(),
            ]),
          )
        ],
      )

Мне нужно, чтобы изображение всегда находилось под заголовком ОС

enter image description here

Я пытался обернуть его с помощью виджета SafeArea, но это не сработало и разбилось

Ответы [ 2 ]

2 голосов
/ 18 июня 2020

Следующее должно работать:

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;
  }
}

Извините за путаницу!

1 голос
/ 18 июня 2020

РЕДАКТИРОВАТЬ №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, который возвращает AppBar, заключенный в виджет SafeArea.

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(),
            ]),
          )
        ],
      ),
    );
  }
}
...