Запретить прокрутку содержимого под SliverAppBar

У меня есть макет Sliver с SliverAppBar вверху, который сворачивается при прокрутке вниз.

Проблема в следующем:

Содержимое моего макета Sliver прокручивается под SliverAppBar: (нежелательно)

введите описание изображения здесь  введите описание изображения здесь

Вместо этого я хочу запретить дальнейшую прокрутку, как только мой SliverAppBar свернут.

Это должно быть максимальное состояние, в котором вы можете прокручивать вниз:

введите здесь описание изображения

Код:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  var scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Home());
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: DefaultTabController(
          length: 2,
          child: NestedScrollView(
            headerSliverBuilder:
                (BuildContext context, bool innerBoxIsScrolled) {
              return [
                SliverAppBar(
                  expandedHeight: 200.0,
                  floating: false,
                  pinned: true,
                  flexibleSpace: FlexibleSpaceBar(
                      centerTitle: true,
                      title: Text("Collapsing Toolbar",
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 16.0,
                          )),
                      background: Image.network(
                        "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
                        fit: BoxFit.cover,
                      )),
                ),
                SliverPadding(
                  padding: new EdgeInsets.all(16.0),
                  sliver: new SliverList(
                    delegate: new SliverChildListDelegate([
                      TabBar(
                        labelColor: Colors.black87,
                        unselectedLabelColor: Colors.grey,
                        tabs: [
                          new Tab(icon: new Icon(Icons.info), text: "Tab 1"),
                          new Tab(
                              icon: new Icon(Icons.lightbulb_outline),
                              text: "Tab 2"),
                        ],
                      ),
                    ]),
                  ),
                ),
              ];
            },
            body: Center(
              child: Text("Sample text"),
            ),
          ),
        ));
  }
}


person Lukas Schneider    schedule 21.11.2019    source источник


Ответы (1)


Вам нужно SliverPersistentHeader и _SliverAppBarDelegate увидеть полный код ниже
Вы можете скопировать и вставить, запустить полный код
подробности, пожалуйста, обратитесь к этому https://medium.com/@diegoveloper/flutter-collapsing-toolbar-sliver-app-bar-14b858e87abe

фрагмент кода

SliverPersistentHeader(
              delegate: _SliverAppBarDelegate(
                TabBar(
                  labelColor: Colors.black87,
                  unselectedLabelColor: Colors.grey,
                  tabs: [
                    Tab(icon: Icon(Icons.info), text: "Tab 1"),
                    Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
                  ],
                ),
              ),
              pinned: true,
            ),

рабочая демонстрация

введите здесь описание изображения

полный код

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  var scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Home());
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: DefaultTabController(
      length: 2,
      child: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return [
            SliverAppBar(
              expandedHeight: 200.0,
              floating: false,
              pinned: true,
              snap: false,
              flexibleSpace: FlexibleSpaceBar(
                  centerTitle: true,
                  title: Text("Collapsing Toolbar",
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 16.0,
                      )),
                  background: Image.network(
                    "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
                    fit: BoxFit.cover,
                  )),
            ),
            SliverPersistentHeader(
              delegate: _SliverAppBarDelegate(
                TabBar(
                  labelColor: Colors.black87,
                  unselectedLabelColor: Colors.grey,
                  tabs: [
                    Tab(icon: Icon(Icons.info), text: "Tab 1"),
                    Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
                  ],
                ),
              ),
              pinned: true,
            ),
          ];
        },
        body: Center(
          child: Text("Sample text"),
        ),
      ),
    ));
  }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate(this._tabBar);

  final TabBar _tabBar;

  @override
  double get minExtent => _tabBar.preferredSize.height;
  @override
  double get maxExtent => _tabBar.preferredSize.height;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(
      child: _tabBar,
    );
  }

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return false;
  }
}
person chunhunghan    schedule 21.11.2019
comment
почему тело будет двигаться раньше SliverAppBar, может пусть вместе двигаются? - person Lucky Dog; 21.11.2019
comment
и если изменить Центр на Контейнер, а затем прокрутить NestedScrollView, это вызовет ненормальную производительность - person Lucky Dog; 21.11.2019
comment
После тестирования мой эмулятор Android по-прежнему отлично работает с Container (). только в первый раз прокрутка не плавная - person chunhunghan; 21.11.2019
comment
Это очень полезно, хотя почему текст (образец текста) все еще перемещается? Как я могу это отключить - person Lukas Schneider; 21.11.2019
comment
Вам нужен tabbarview - person chunhunghan; 21.11.2019
comment
@chunhunghan Если я просто хочу отобразить listView, tabbar - это просто индикатор индекса, как отобразить этот listView? Я пытаюсь установить новый TabController (vsync: this, length: 1) для tabBarView ,, но он выдает исключение: Controller's length property (0) does not match the number of tabs (3) present in TabBar's tabs property., поэтому мы будем благодарны за любые предложения. - person Lucky Dog; 21.11.2019
comment
Я бы посоветовал разместить ваш код в новом вопросе, чтобы больше людей могли вам помочь. текущий вопрос не соответствует вашему новому запросу. - person chunhunghan; 25.11.2019
comment
убедитесь, что _tabController = TabController (vsync: this, length: 5); длина вашего контроллера вкладок равна вашему количеству вкладок - person chunhunghan; 25.11.2019
comment
Я хотел бы знать, как остановить перемещение образца текста. - person Victor Roberti Camolesi; 18.11.2020