Flutter开发·含有ListView等滚动组件的Dialog高度自适应显示问题

2,347 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

之前写到一个App内显示升级弹框需求,大体样式如下:

16464021-bb52141662346eb3.jpeg

其中,升级说明的条数不固定,可多可少,所以这里要满足的要求有:弹框高度要根据升级条目的多少自适应,但是为了美观最高不能超过600,当条目很多时需要可以滚动。 为了要满足要求肯定要使用Listview + Flexible + Container的maxHeight属性进行布局。一开始的代码是这样的:

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 30),
      constraints: BoxConstraints(
          maxHeight: 700
      ),
      color: Colors.white,
      width: 500,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            padding: const EdgeInsets.all(20),
            child: Text("新版本来啦~",style: TextStyle(
              color: Colors.black,
              fontSize: 50,)),
          ),
          listItems(),
          Container(
            padding: const EdgeInsets.all(20),
            child: Text("立即升级",style: TextStyle(
              color: Colors.red,
              fontSize: 30,)),
          ),
        ],
      ),
    );
  }

  Widget listItems() {
    List<Widget> updateList = [];
    list.forEach((item) {
      updateList.add(Text(
        '$item',
        style: TextStyle(
          color: Colors.black,
          fontSize: 30,),
      ));
    });
    return Flexible(
      child: ListView(
        children: updateList,
      ),
    );
  }

maxHeight,ListView,Flexible全都有了,但是运行起来就发现了问题:当升级文案条目很少的时候高度依然也会达到maxHeight设置的最大值600.想想一定是因为listview自动将高度撑大到了他所能到的父布局的最大高度。那么从这个方向入手终于在网上找到了答案,那便是设置listview的shrinkWrap为true即可。

ListView(
   shrinkWrap: true,
   children: updateList,
)      

Flutter中给出这个属性的解释是:**该属性将决定列表的长度是否仅包裹其内容的长度,**默认值为false,也就是说默认情况是自动将listview高度延伸到最大,基本上所有的滚动组件都有这个属性。 其实之前是用到过这个属性的,当时也没有深入研究其含义。趁此机会可以再复习一下ListView组件中属性的介绍:

ListView({
  Axis scrollDirection = Axis.vertical,
  ScrollController controller,
  ScrollPhysics physics,
  bool shrinkWrap = false,
  EdgeInsetsGeometry padding,
  this.itemExtent,
  double cacheExtent,
  List<Widget> children = const <Widget>[],
})
  • scrollDirection: 列表的滚动方向,可选值有Axis的horizontal和vertical,可以看到默认是垂直方向上滚动;
  • controller : 控制器,与列表滚动相关,比如监听列表的滚动事件;
  • physics: 列表滚动至边缘后继续拖动的物理效果,Android与iOS效果不同。Android会呈现出一个波纹状(对应ClampingScrollPhysics),而iOS上有一个回弹的弹性效果(对应BouncingScrollPhysics)。如果你想不同的平台上呈现各自的效果可以使用AlwaysScrollableScrollPhysics,它会根据不同平台自动选用各自的物理效果。如果你想禁用在边缘的拖动效果,那可以使用NeverScrollableScrollPhysics;
  • shrinkWrap: 该属性将决定列表的长度是否仅包裹其内容的长度。当ListView嵌在一个无限长的容器组件中时,shrinkWrap必须为true,否则Flutter会给出警告;
  • padding: 列表内边距;
  • itemExtent: 子元素长度。当列表中的每一项长度是固定的情况下可以指定该值,有助于提高列表的性能(因为它可以帮助ListView在未实际渲染子元素之前就计算出每一项元素的位置);
  • cacheExtent: 预渲染区域长度,ListView会在其可视区域的两边留一个-cacheExtent长度的区域作为预渲染区域(对于ListView.build或ListView.separated构造函数创建的列表,不在可视区域和预渲染区域内的子元素不会被创建或会被销毁);
  • children: 容纳子元素的组件数组。 代码地址