Flutter记录的第五天 滚动控件

一、SingleChildScrollView

SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件。定义如下:

SingleChildScrollView({
  this.scrollDirection = Axis.vertical, //滚动方向,默认是垂直方向
  this.reverse = false, 
  this.padding, 
  bool primary, 
  this.physics, 
  this.controller,
  this.child,
})

需要注意的是,通常SingleChildScrollView只应在期望的内容不会超过屏幕太多时使用,这是因为SingleChildScrollView不支持基于Sliver的延迟实例化模型,所以如果预计视口可能包含超出屏幕尺寸太多的内容时,那么使用SingleChildScrollView将会非常昂贵(性能差),此时应该使用一些支持Sliver延迟加载的可滚动组件,如ListView

示例

下面是一个将大写字母A-Z沿垂直方向显示的例子,由于垂直方向空间会超过屏幕视口高度,所以我们使用SingleChildScrollView

class SingleChildScrollViewTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    return Scrollbar( // 显示进度条
      child: SingleChildScrollView(
        padding: EdgeInsets.all(16.0),
        child: Center(
          child: Column( 
            //动态创建一个List<Widget>  
            children: str.split("") 
                //每一个字母都用一个Text显示,字体为原来的两倍
                .map((c) => Text(c, textScaleFactor: 2.0,)) 
                .toList(),
          ),
        ),
      ),
    );
  }
}

运行效果如图所示:

图6-1

二、Listview

ListView是我们最常用的组件之一,用于展示大量数据的列表。

#构建方式

数据较少时,可以直接使用如下方式:

ListView(
  children: <Widget>[
    item,item1,item2,
  ],
)

这种方式一次加载所有的组件,没有“懒加载”,因此当有大量数据时,使用动态创建列表的方式:

ListView.builder(
  itemBuilder: (BuildContext context, int index) {
    return Text('Item$index');
  },
  itemExtent: 50,
)

如果想在每一项中间增加分割线可以使用如下方式:

ListView.separated(
  itemBuilder: (BuildContext context, int index) {
    return Text('Item$index');
  },
  separatorBuilder: (BuildContext context, int index){
    return Divider();
  },
  itemCount: 50,
)

一般上面的方式就够用了,如果以上都不能满足你的要求,还可以使用ListView.custom,自定义SliverChildDelegate构建自己的ListView。

#基础属性

通过scrollDirection参数控制滚动方向,默认是垂直方向,向上滚动,设置为水平方向:

ListView.builder(
    scrollDirection: Axis.horizontal,
    ...
)

滚动方向如果是垂直方向,默认是向上滚动,通过reverse参数设置其向下滚动,代码如下:

ListView.builder(
    reverse: true,
    ...
)

controller可以控制ListView的滚动,比如获取当前滚动的位置,或者代码直接滚动到指定位置,用法如下:

ScrollController controller;
  @override
  void initState() {
    super.initState();
    controller = ScrollController()
    ..addListener((){
      print('${controller.position}');
    });
    
  }
  
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        controller:controller,
        itemBuilder: (context, index) {
          return Text('Item $index');
        });
  }

physics参数控制滚动到物理特性,比如设置为不可滚动:

ListView.builder(
    physics: NeverScrollableScrollPhysics(),
  ···
)

系统提供的ScrollPhysics有:

  • AlwaysScrollableScrollPhysics:总是可以滑动
  • NeverScrollableScrollPhysics:禁止滚动
  • BouncingScrollPhysics :内容超过一屏 上拉有回弹效果
  • ClampingScrollPhysics :包裹内容 不会有回弹

addAutomaticKeepAlives参数表示当关闭屏幕时Item是否进行垃圾回收,默认为true。

三、GridView

GridView是一个可滚动的,2D数组控件。

基本用法如下:

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
  ),
  children: [
    _createGridViewItem(Colors.primaries[0]),
    _createGridViewItem(Colors.primaries[1]),
    _createGridViewItem(Colors.primaries[2]),
    _createGridViewItem(Colors.primaries[3]),
    _createGridViewItem(Colors.primaries[4]),
    _createGridViewItem(Colors.primaries[5]),
    _createGridViewItem(Colors.primaries[6]),
    _createGridViewItem(Colors.primaries[7]),

  ],
)
_createGridViewItem(Color color){
    return Container(
      height: 80,
      color: color,
    );
  }

效果如下:

gridDelegate参数控制子控件的排列,有2个选择:

  • SliverGridDelegateWithFixedCrossAxisCount:交叉轴方向上固定数量,对于垂直方向的GridView来说交叉轴方向指的是水平方向。
  • SliverGridDelegateWithMaxCrossAxisExtent:交叉轴方向上尽量大,比如水平方上有500空间,指定此值为150,那么可以放3个,剩余一些空间,此时GridView将会缩小每一个Item,放置4个。

SliverGridDelegateWithFixedCrossAxisCount有属性介绍如下:

  • crossAxisCount:交叉轴方向上个数。
  • mainAxisSpacing:主轴方向上2行之间的间隔。
  • crossAxisSpacing:交叉轴方向上之间的间隔。
  • childAspectRatio:子控件宽高比。

设置间隔如下:

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
    crossAxisSpacing: 2,
    mainAxisSpacing: 4
  )
  ...
)

效果如下:

scrollDirection`表示滚动方向,默认是垂直方向,可以设置为水平方向。

reverse表示是否反转滚动方向,比如当前滚动方向是垂直方向,reverse设置为true,滚动方向为从上倒下,设置为false,滚动方向为从下倒上。

用法如下:

GridView(
  scrollDirection: Axis.horizontal,
  reverse: true,
  ...
)

controller表示滚动相关,可以通过ScrollController获取到当前滚动位置,或者指定滚动到某一位置,用法如下:

ScrollController _gridViewController;

@override
  void initState() {
    _gridViewController = ScrollController()..addListener(() {
      print('${_gridViewController.position}');
    });
  }
  
GridView(
  controller: _gridViewController,
	...
)

physics参数控制滚动到物理特性,比如设置为不可滚动:

GridView(
    physics: NeverScrollableScrollPhysics(),
  ···
)

系统提供的ScrollPhysics有:

  • AlwaysScrollableScrollPhysics:总是可以滑动
  • NeverScrollableScrollPhysics:禁止滚动
  • BouncingScrollPhysics :内容超过一屏 上拉有回弹效果
  • ClampingScrollPhysics :包裹内容 不会有回弹

直接使用最开始的方法创建GridView是不推荐的,此方法不适合加载大量数据的情况,GridView提供了一些快速构建的方法,比如builder,用法如下:

GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
  ),
  itemBuilder: (context, index) {
    return Container(
      height: 80,
      color: Colors.primaries[index % Colors.primaries.length],
    );
  },
  itemCount: 50,
)

itemBuilder是构建子控件,itemCount指定数据个数。

使用GridView.custom构建:

GridView.custom(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
  ),
  childrenDelegate: SliverChildBuilderDelegate((context, index) {
    return Container(
        height: 80,
        color: Colors.primaries[index % Colors.primaries.length]);
  }, childCount: 50),
)

使用GridView.count构建:

GridView.count(
  crossAxisCount: 3,
  children: List.generate(50, (i) {
    return Container(
      height: 80,
      color: Colors.primaries[i % Colors.primaries.length],
    );
  }),
)

使用GridView.extent构建:

GridView.extent(
  maxCrossAxisExtent: 100,
  children: List.generate(50, (i) {
    return Container(
      height: 80,
      color: Colors.primaries[i % Colors.primaries.length],
    );
  }),
)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值