美文网首页
Flutter学习(八)滚动Widget

Flutter学习(八)滚动Widget

作者: yanhooIT | 来源:发表于2020-04-16 00:03 被阅读0次

    ListView

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text("ListView"),
            ),
            body: HomeView(),
          ),
        );
      }
    }
    
    class HomeView extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ListViewDemo3();
      }
    }
    
    class ListViewDemo3 extends StatelessWidget {
      const ListViewDemo3({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        /** ListView.separated
         *
         *  根据子元素的布局父组件会自适应高度
         */
        return ListView.separated(
          itemCount: 100,
          itemBuilder: (BuildContext ctx, int index) {
            return Text(
              "Hello World: $index",
              style: TextStyle(fontSize: 20),
            );
          },
          // 构建分割Widget
          separatorBuilder: (BuildContext ctx, int index) {
            // 分隔线
            return Divider(
              color: Colors.red,
              // 设置Divider的高度
              height: 30,
              // 设置距起始位置的距离
              indent: 10,
              // 设置距结尾位置的距离
              endIndent: 10,
              // 设置线高
              thickness: 2,
            );
          },
        );
      }
    }
    
    class ListViewDemo2 extends StatelessWidget {
      const ListViewDemo2({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        /** ListView.builder(这个比较常用)
         *
         *  适合动态创建子元素
         */
        return ListView.builder(
          // 要创建多少个子元素
          itemCount: 100,
          // 设置固定高度
          itemExtent: 60,
          // 当即将显示到屏幕上时才开始构建
          itemBuilder: (BuildContext ctx, int index) {
            return Text(
              "Hello World: $index",
              style: TextStyle(fontSize: 20),
            );
          },
        );
      }
    }
    
    class ListViewDemo1 extends StatelessWidget {
      const ListViewDemo1({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return ListView(
          // 设置滚动方向
    //      scrollDirection: Axis.horizontal,
          // 显示反转
    //      reverse: true,
          // 设置子组件的固定高度
          // 当设置scrollDirection: Axis.horizontal,须指定每一个item的固定宽度
          itemExtent: 80,
          /**  ListView.generate批量创建ListView的子元素
           *
           * (1)只适合子元素比较少的场景,如果元素比较多就会比较耗费内存
           * (2)动态不固定的的子元素不建议用此方法,建议用List.builder替代
           */
          children: List.generate(100, (index) {
            return ListTile(
              // 左边显示的组件
              leading: Icon(Icons.people),
              // 右边显示的组件
              trailing: Icon(Icons.delete),
              // 主标题
              title: Text("联系人${index + 1}"),
              // 子标题
              subtitle: Text("联系人电话号码:18866665555"),
            );
          }),
        );
      }
    }
    

    GridView

    import 'package:flutter/material.dart';
    import 'dart:math';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text("GridView"),
            ),
            body: HomeView(),
          ),
        );
      }
    }
    
    class HomeView extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return GridViewDemo3();
      }
    }
    
    class GridViewDemo3 extends StatelessWidget {
      const GridViewDemo3({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        /// 这种方式在开发中比较常用
        return GridView.builder(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              // 每一行固定显示几个
                crossAxisCount: 3,
                // 宽高比,即:这个比率 = 宽度 / 高度,可以根据这个值来确定子元素的高度
                childAspectRatio: 2,
                // 交叉轴每个子元素之间的间距
                crossAxisSpacing: 8,
                // 主轴每个子元素之间的间距
                mainAxisSpacing: 20
            ),
            itemBuilder: (BuildContext ctx, int index) {
              return Container(
                color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)),
              );
            }
        );
      }
    }
    
    class GridViewDemo2 extends StatelessWidget {
      const GridViewDemo2({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GridView(
          gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
            // 设置固定宽度
            maxCrossAxisExtent: 400,
            // 宽高比,即:这个比率 = 宽度 / 高度,可以根据这个值来确定子元素的高度
            childAspectRatio: 2,
            crossAxisSpacing: 8,
            mainAxisSpacing: 20,
          ),
          children: List.generate(100, (index) {
            return Container(
              color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)),
            );
          }),
        );
      }
    }
    
    class GridViewDemo1 extends StatelessWidget {
      const GridViewDemo1({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GridView(
          // 固定子元素个数
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            // 每一行固定显示几个
              crossAxisCount: 3,
              // 宽高比,即:这个比率 = 宽度 / 高度,可以根据这个值来确定子元素的高度
              childAspectRatio: 2,
              // 交叉轴每个子元素之间的间距
              crossAxisSpacing: 8,
              // 主轴每个子元素之间的间距
              mainAxisSpacing: 20
          ),
          children: List.generate(100, (index) {
            return Container(
              color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)),
            );
          }),
        );
      }
    }
    

    CustomScrollView

    import 'package:flutter/material.dart';
    import 'dart:math';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
    //        appBar: AppBar(
    //          title: Text("CustomScrollView"),
    //        ),
            body: HomeView(),
          ),
        );
      }
    }
    
    class HomeView extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return CustomScrollView2();
      }
    }
    
    class CustomScrollView2 extends StatelessWidget {
      const CustomScrollView2({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return CustomScrollView(
          slivers: <Widget>[
            // 属于滚动条的导航栏
            SliverAppBar(
              // 固定导航栏
              pinned: true,
              // 设置导航栏的扩展区域高度
              expandedHeight: 200,
              // 设置在扩展区域要显示的内容
              flexibleSpace: FlexibleSpaceBar(
                title: Container(
                    color: Colors.black,
                    child: Text("Hello World", style: TextStyle(color: Colors.white, fontSize: 20),)),
                // BoxFit.cover:会按图片的长宽比放大后居中填满显示空间,图片不会变形,超出显示空间部分会被剪裁
                background: Image.asset("assets/images/xuebao.png", fit: BoxFit.cover),
              ),
            ),
            // 类似GridView
            SliverGrid(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 8,
                  mainAxisSpacing: 8,
                  childAspectRatio: 2
              ),
              delegate: SliverChildBuilderDelegate(
                      (BuildContext ctx, int int) {
                    return Container(color: Color.fromARGB(255, Random().nextInt(
                        256), Random().nextInt(256), Random().nextInt(256)));
                  },
                  // 显示四个元素
                  childCount: 4
              ),
            ),
            // 类似ListView
            SliverList(
              delegate: SliverChildBuilderDelegate(
                      (BuildContext ctx, int index) {
                    return ListTile(
                      leading: Icon(Icons.people),
                      title: Text("联系人$index"),
                    );
                  },
                  childCount: 20
              ),
            )
          ],
        );
      }
    }
    
    class CustomScrollView1 extends StatelessWidget {
      const CustomScrollView1({
        Key key,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        /// 可以统一管理多个滚动视图
        /// 在CustomScrollView中,每一个独立的,可滚动的Widget被称之为Sliver
        return CustomScrollView(
          slivers: <Widget>[
            // 设置安全区域,只在安全区域里显示,类似的还有SafeArea
            SliverSafeArea(
              // 设置内间距
              sliver: SliverPadding(
                padding: EdgeInsets.all(8),
                /// SliverGrid类似于我们之前使用过的GridView
                sliver: SliverGrid(
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      crossAxisSpacing: 8,
                      mainAxisSpacing: 8,
                      childAspectRatio: 1.5
                  ),
                  // 设置代理,之前的generate、builder方法分别对应SliverChildListDelegate、SliverChildBuilderDelegate
                  delegate: SliverChildBuilderDelegate(
                          (BuildContext ctx, int int) {
                        return Container(color: Color.fromARGB(255, Random().nextInt(
                            256), Random().nextInt(256), Random().nextInt(256)));
                      },
                      // 一共有多少个元素,不设置就是无限个
                      childCount: 20
                  ),
                ),
              ),
            )
          ],
        );
      }
    }
    

    事件监听

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: '监听滚动事件',
          theme: ThemeData(
              primarySwatch: Colors.blue, splashColor: Colors.transparent),
          home: HomeView(),
        );
      }
    }
    
    class HomeView extends StatefulWidget {
      @override
      _HomeViewState createState() => _HomeViewState();
    }
    
    class _HomeViewState extends State<HomeView> {
      // 可以指定初始的偏移量,这里直接设置为0,没有初始偏移量
      ScrollController _controller = ScrollController(initialScrollOffset: 0);
      bool _isShowFloatingBtn = false;
    
      @override
      void initState() {
        super.initState();
    
        _controller.addListener(() {
          print("监听到滚动....: ${_controller.offset}");
    
          setState(() {
            _isShowFloatingBtn = _controller.offset >= 300;
          });
        });
      }
    
      @override
      Widget build(BuildContext context) {
        /**
         * 两种方式可以监听:
         *
         *  1、controller:
         *    可以设置默认值offset
         *    监听滚动, 也可以监听滚动的位置
         *
         *  2、NotificationListener
         *    开始滚动 和 结束滚动
         */
        return Scaffold(
          appBar: AppBar(
            title: Text("监听滚动事件"),
          ),
          body: NotificationListener(
            onNotification: (ScrollNotification notification) {
              if (notification is ScrollStartNotification) {
                print("开始滚动,可滚动距离:${notification.metrics.maxScrollExtent}");
              } else if (notification is ScrollUpdateNotification) {
                print(
                    "正在滚动... 当前滚动的位置: ${notification.metrics.pixels}");
              } else if (notification is ScrollEndNotification) {
                print("结束滚动");
              }
    
              // 返回一个布尔值,代表是否阻止该事件继续向上冒
              // 如果为true时,则冒泡终止,事件停止向上传播
              // 如果不返回 或者 返回值为false时,则冒泡继续
              return true;
            },
            child: ListView.builder(
                controller: _controller,
                itemCount: 30,
                itemBuilder: (BuildContext ctx, int index) {
                  return ListTile(
                    leading: Icon(Icons.people),
                    title: Text("联系人$index"),
                  );
                }),
          ),
          floatingActionButton: _isShowFloatingBtn
              ? FloatingActionButton(
            child: Icon(Icons.arrow_upward),
            onPressed: () {
              // 滚动到顶部
              // jumpTo没有动画效果
    //                _controller.jumpTo(0);
    
              // animateTo是带动画效果的
              _controller.animateTo(0, duration: Duration(seconds: 1), curve: Curves.easeIn);
            },
          )
              : null,
        );
      }
    
      @override
      void dispose() {
        super.dispose();
    
        _controller.dispose();
      }
    }
    

    相关文章

      网友评论

          本文标题:Flutter学习(八)滚动Widget

          本文链接:https://www.haomeiwen.com/subject/wyscmhtx.html