Flutter CustomScrollView使用介绍

Flutter CustomScrollView支持自定义内部item的滚动控件,还支持头部带滑动缩放的SliverAppBar。需要注意如果CustomScrollView的item嵌套了和他滚动方向相同的控件这不能正常滑动,因为CustomScrollView内部只会维护一个Scrollable而会子控件会优先消费就会出现只有子控件能滚动的问题。如果有这种需求的场景建议使用NestedScrollView可以自定义Sliver

       ///
/// CustomScrollView 滚动
class CustomScrollViewApp extends StatelessWidget {
  const CustomScrollViewApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => _CustomScrollViewPage();
}

class _CustomScrollViewPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _CustomScrollViewState();
}

class _CustomScrollViewState extends State<_CustomScrollViewPage> {
  var controller = ScrollController();

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
          home: Scaffold(
        bottomNavigationBar: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              child: const Text('当前滑动'),
              onPressed: () {
                print('滑动offset=${controller.offset}');
                print('滑动position=${controller.positions.length}');
              },
            ),
            const SizedBox(
              width: 20,
            ),
            ElevatedButton(
              child: const Text('滑动到最上'),
              onPressed: () {
                //设置带动画滑动到指定位置
                controller.animateTo(0,
                    duration: const Duration(milliseconds: 500), //动画持续时长
                    curve: Curves.easeInCubic); //以哪种动画的方式滑动
              },
            ),
          ],
        ),
        body: CustomScrollView(
          controller: controller,
          slivers: <Widget>[
            //顶部的标题内容,添加[expandedHeight]属性后支持列表滑动缩放
            SliverAppBar(
              //缩放到最小时是否需要悬停到顶部
              pinned: true,
              //缩放的最大高度,必须要设置了才会有缩放的效果
              expandedHeight: 250.0,
              flexibleSpace: FlexibleSpaceBar(
                //标题是否居中
                centerTitle: true,
                //标题padding
                titlePadding: const EdgeInsets.all(10),
                //背景缩放模式 CollapseMode.pin//背景跟着一起往上滚,CollapseMode.none//背景不动
                collapseMode: CollapseMode.parallax,
                background: Image.network(
                  'https://tse4-mm.cn.bing.net/th/id/OIP-C.E-4fLhTRC4aG-RvqTAO_dwHaE8?w=251&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
                  fit: BoxFit.cover,
                ),
                title: const Text('万物生长'),
              ),
            ),
            //卡片样式的item,意思就是一行可以排列多个
            SliverGrid(
              gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
                //单个item最大宽度,一行不排列不够就换到下一行
                maxCrossAxisExtent: 200.0,
                //横轴的间距
                mainAxisSpacing: 10.0,
                //数轴的间距
                crossAxisSpacing: 10.0,
                //item宽高比列
                childAspectRatio: 4,
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment.center,
                    color: Colors.teal[100 * (index % 9)],
                    child: Text(
                      'Grid Item $index',
                      style: const TextStyle(fontSize: 15),
                    ),
                  );
                },
                //item条数
                childCount: 20,
              ),
            ),
            //自定义item
            SliverToBoxAdapter(
                child: SizedBox(
              height: 300,
              child: PageView(
                children: [
                  Stack(
                    alignment: Alignment.bottomCenter,
                    children: [
                      Image.network(
                        'https://tse1-mm.cn.bing.net/th/id/OIP-C.d0NDc_VMqt8RrQXWzu7zvQHaE7?w=295&h=197&c=7&r=0&o=5&dpr=2&pid=1.7',
                        fit: BoxFit.cover,
                      ),
                      const Text(
                        '这是第一个',
                        style: TextStyle(fontSize: 30, color: Colors.white),
                      ),
                    ],
                  ),
                  Image.network(
                    'https://tse2-mm.cn.bing.net/th/id/OIP-C.zsnUfFGwV6T3G9ENQpu2BQHaL3?w=122&h=197&c=7&r=0&o=5&dpr=2&pid=1.7',
                    fit: BoxFit.cover,
                  ),
                  Image.network(
                    'https://tse4-mm.cn.bing.net/th/id/OIP-C.BEBN8oSQVet6K2qUFkIMYgHaET?w=294&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
                    fit: BoxFit.cover,
                  ),
                  Image.network(
                    'https://tse2-mm.cn.bing.net/th/id/OIP-C.QnTEUd-GHD5B2cTgalo4-QHaEK?w=333&h=187&c=7&r=0&o=5&dpr=2&pid=1.7',
                    fit: BoxFit.cover,
                  ),
                ],
              ),
            )),
            //包裹可以设置间距
            SliverPadding(
              padding: const EdgeInsets.all(20),
              sliver: //固定单条item
                  SliverFixedExtentList(
                //item高度
                itemExtent: 50.0,
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  return Container(
                    alignment: Alignment.center,
                    color: Colors.lightBlue[100 * (index % 9)],
                    child: Text('List Item $index'),
                  );
                  //item条数
                }, childCount: 20),
              ),
            ),
            //单条一行
            SliverList(
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
              return Container(
                height: 40,
                alignment: Alignment.center,
                color: Colors.green[100 * (index % 9)],
                child: Text('Sliver List Item $index'),
              );
              //item条数
            }, childCount: 20)),
          ],
        ),
      ));
}


版权声明:本文为qq_30005223原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。