当前位置:   article > 正文

Flutter滚动组件的使用逻辑

Flutter滚动组件的使用逻辑

什么是滚动组件?
滚动组件指可以通过滚动(滑动)手势控制可见区域的组件,在Flutter中可以分为盒子布局(RenderBox)和滚动布局(RenderSliver),我们本次讨论的就是构建滚动布局的组件
滚动组件有哪些
按照类型可以分为完整滚动组件和Sliver类型组件,常见的完整滚动组件有:ListView、GridView、PageView等,常见的Sliver类型组件有SliverList,SliverGrid、SliverFixedExtentList等
什么是Sliver类型组件?为什么需要使用Sliver类型的滚动组件?
Sliver类型组件也是滚动组件,只是它们并非是完整的,即无法单独的存在,完整的滚动组件包含Scrollable、Viewport和Sliver,但是完整的滚动组件也只能在页面中存在一个,如果我们需要在页面中构建多个可滚动组件,那么我们就需要使用Sliver组件进行构建,可以认为Sliver组件是功能组件的多滚动环境替代品

Sliver组件一般以Sliver开头或结尾,从名字大抵就可以判断它的替代对象是谁,比如SliverList与ListView,SliverGrid与GridView

如何使用Sliver组件?
Sliver组件可以通过CustomScrollView组件来构建,CustomScrollView允许定义多个Sliver类型组件,我们可以基于以上,构建一个比较完整的页面结构

在这里插入图片描述

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});


  
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late TabController _controller;

  
  void initState() {
    super.initState();
    _controller = TabController(length: 2, vsync: this);

    _controller.addListener(() {
      if (kDebugMode) {
        print(_controller.index);
      }
    });
  }


  _mySliverChildBuilderDelegate() {
    return SliverChildBuilderDelegate(
          (BuildContext context, int index) {
        return Container(
          height: 30,
          color: Colors.primaries[index % 8],
        );
      },
      childCount: 20,
    );
  }

  _mySliverGridDelegateWithFixedCrossAxisCount() {
    return const SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 5,
      mainAxisSpacing: 10,
      crossAxisSpacing: 5,
      childAspectRatio: 1,
    );
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: const Text('Sliver Demo'),
              bottom: TabBar(
                controller: _controller,
                tabs: const <Widget>[
                  Tab(text: 'Tab1'),
                  Tab(text: 'Tab2'),
                ],
              ),
            ),
            body: TabBarView(
              controller: _controller,
              children: <Widget>[
                CustomScrollView(
                  slivers: [
                    SliverGrid(
                      delegate: _mySliverChildBuilderDelegate(),
                      gridDelegate:
                      _mySliverGridDelegateWithFixedCrossAxisCount(),
                    ),
                    SliverList(delegate: _mySliverChildBuilderDelegate())
                  ],
                ),
                const Text('Tab2 content'),
              ],
            )));
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

上述结构中使用了Scaffold脚手架定义了固定的AppBar,但是如果想要将AppBar替换为动态的SliverAppBar(一般是下拉缩小或隐藏),那么继续使用CustomScrollView来构建就会麻烦许多了,特别与TarBarView的融合,这时我们可以使用NestedScrollView组件来构建
NestedScrollView提供了一个包含header、body两段结构的框架,header中允许定义多个Sliver类型的组件,body中允许定义一个完整滚动组件,当然,我们也可以定义为CustomScrollView类型,实现如下:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});


  
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late TabController _controller;

  
  void initState() {
    super.initState();
    _controller = TabController(length: 2, vsync: this);

    _controller.addListener(() {
      if (kDebugMode) {
        print(_controller.index);
      }
    });
  }


  _mySliverChildBuilderDelegate() {
    return SliverChildBuilderDelegate(
          (BuildContext context, int index) {
        return Container(
          height: 30,
          color: Colors.primaries[index % 8],
        );
      },
      childCount: 20,
    );
  }

  _mySliverGridDelegateWithFixedCrossAxisCount() {
    return const SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 5,
      mainAxisSpacing: 10,
      crossAxisSpacing: 5,
      childAspectRatio: 1,
    );
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
        home:   NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
              return <Widget>[
                SliverAppBar(
                  title: const Text('Sliver Demo'),
                  pinned: true,
                  expandedHeight: 100,
                  forceElevated: innerBoxIsScrolled,
                  bottom: TabBar(
                    controller: _controller,
                    tabs: const <Widget>[
                      Tab(text: 'Tab1'),
                      Tab(text: 'Tab2'),
                    ],
                  ),
                )];
            },
            body: TabBarView(
              controller: _controller,
              children: <Widget>[
                CustomScrollView(
                  slivers: [
                    SliverGrid(
                      delegate: _mySliverChildBuilderDelegate(),
                      gridDelegate:
                      _mySliverGridDelegateWithFixedCrossAxisCount(),
                    ),
                    SliverList(delegate: _mySliverChildBuilderDelegate())
                  ],
                ),
                const Text('Tab2 content'),
              ],
            )));
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/463056
推荐阅读
相关标签
  

闽ICP备14008679号