前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[- Flutter 基础篇 -] ListView的使用

[- Flutter 基础篇 -] ListView的使用

作者头像
张风捷特烈
发布2020-04-30 15:19:25
9680
发布2020-04-30 15:19:25
举报
1.ListView 的基本使用

ListView 是一个盛放多个孩子的容器。我们从下面的例子开始介入:


1.1:三个构造
  • 使用ListView构造方法

和Flex,Wrap类似,将子元素一个一个按顺序排列。

代码语言:javascript
复制
var caverStyle= TextStyle(fontSize: 18, shadows: [//文字样式
  Shadow(
      color: Colors.white, offset: Offset(-0.5, 0.5), blurRadius: 0)
]);
var show = ListView(//ListView的构造方法
  padding: EdgeInsets.all(8.0),//边距
  children: <Widget>[//孩子们
    Container(
      height: 50,
      color: Color(0xffff0000),
      child: Center(child: Text('红色',style: caverStyle,)),
    ),
    Container(
      height: 50,
      color: Color(0xffFFFF00),
      child: Center(child: Text('黄色',style: caverStyle,)),
    ),
    Container(
      height: 50,
      color: Color(0xff00FF00),
      child: Center(child: Text('绿色',style: caverStyle,)),
    ),
    Container(
      height: 50,
      color: Color(0xff0000FF),
      child: Center(child: Text('蓝色',style: caverStyle,)),
    ),
  ],
);

  • 使用ListView.builder方法构造

使用builder方法对List或Map数据进行批量生成。

代码语言:javascript
复制
const colorMap = {//数据来源
  0xffff0000: "红色",
  0xffFFFF00: "黄色",
  0xff00FF00: "绿色",
  0xff0000FF: "蓝色",
};
var caverStyle= TextStyle(fontSize: 18, shadows: [//文字样式
  Shadow(
      color: Colors.white, offset: Offset(-0.5, 0.5), blurRadius: 0)
]);
var show = ListView.builder(//使用builder方法进行构造
    padding: EdgeInsets.all(8.0),
    itemCount: colorMap.length,//条目的个数
    itemBuilder: (BuildContext context, int index) {//条目构造器
      return Container(
        height: 50,
        color: Color(colorMap.keys.toList()[index]),
        child: Center(
            child: Text(
          '${colorMap.values.toList()[index]}',
          style: caverStyle,
        )),
      );
    });

  • 使用ListView.separated方法构造

separated方法和builder类似,但是可以通过separatorBuilder属性创建分隔线。

代码语言:javascript
复制
const colorMap = {//数据来源
  0xffff0000: "红色",
  0xffFFFF00: "黄色",
  0xff00FF00: "绿色",
  0xff0000FF: "蓝色",
};
var caverStyle = TextStyle(fontSize: 18, shadows: [//文字样式
  Shadow(color: Colors.white, offset: Offset(-0.5, 0.5), blurRadius: 0)
]);
var show = ListView.separated(//使用separated方法进行构造
  padding: EdgeInsets.all(8.0),
    itemBuilder: (context, index) {//条目构造器
      return Container(
        height: 50,
        color: Color(colorMap.keys.toList()[index]),
        child: Center(
            child: Text(
          '${colorMap.values.toList()[index]}',
          style: caverStyle,
        )),
      );
    },
    separatorBuilder: (context, index) {//分隔线构造器
      return Container();
    },
    itemCount: colorMap.length);

2.ListView进阶使用
2.1:完成条目的封装

比较简单,我也不分析这么布局了,直接上代码。

  • 信息描述类
代码语言:javascript
复制
class PoemItem {
  ImageProvider image;//图片
  var title;//标题
  var author;//作者
  var summary;//摘要
  PoemItem({this.image, this.title, this.author, this.summary});
}
  • 条目的封装
代码语言:javascript
复制
typedef OnItemClickListener = void Function();
class PoemItemView extends StatelessWidget {
  final PoemItem data;
  final OnItemClickListener onItemClickListener;
  PoemItemView({Key key, this.data, this.onItemClickListener})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    var headIcon = Container(//左边头部
        decoration: BoxDecoration(
          color: Colors.white,
          shape: BoxShape.circle,
          boxShadow: [
            BoxShadow(
              color: Colors.grey.withOpacity(0.3),
              offset: Offset(0.0, 0.0),
              blurRadius: 3.0,
              spreadRadius: 0.0,
            ),
          ],
        ),
        width: 70,
        height: 70,
        child: Padding(
          padding: EdgeInsets.all(3),
          child: CircleAvatar(
            backgroundImage: data.image,
          ),
        ));
    var center = Column(//中间介绍
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Text(data.title,
            style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
        Padding(
          padding: EdgeInsets.only(top: 8),
          child: Text(
            "作者:${data.author}",
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
        ),
      ],
    );
    var summary = Text(//尾部摘要
      data.summary,
      maxLines: 3,
      overflow: TextOverflow.ellipsis,
      style: TextStyle(color: Colors.grey, fontSize: 12),
    );
    var item = Row(//条目拼合
      mainAxisAlignment: MainAxisAlignment.start,
      children: <Widget>[
        SizedBox(width: 10),
        headIcon,
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 20),
          child: center,
        ),
        Expanded(
          child: summary,
        ),
        SizedBox(width: 10),
      ],
    );
    var result = Card(//卡片化+事件监听
        elevation: 5,
        child: InkWell(
            onTap: onItemClickListener,
            child: Padding(
              padding: EdgeInsets.all(10),
              child: item,
            )));
    return result;
  }
}
复制代码
2.2:ListView的使用

在构造器构造条目时,使用数据对条目进行数据填充,侧达到数据展示效果

代码语言:javascript
复制
var data = <PoemItem>[];
for (var i = 0; i < 20; i++) {
  data.add(PoemItem(
      image: AssetImage("images/wy_200x300.jpg"),
      title: "$i:以梦为马",
      author: "海子",
      summary: "我要做远方的忠诚的儿子,和物质的短暂情人,和所有以梦为马的诗人一样,我不得不和烈士和小丑走在同一道路上"));
}
var show = ListView.builder(
    padding: EdgeInsets.all(8.0),
    itemCount: data.length, //条目的个数
    itemBuilder: (BuildContext context, int index) {
      return PoemItemView(//数据填充条目
        data: data[index],
        onItemClickListener: () {//事件响应
          print(index);
        },
      );
    });
复制代码

2.3:分隔线的添加

这里现将Card组件去掉。separated可以很轻松的实现下划线分隔,并且容易改变长短,颜色 如果你愿意,也可以去定义分隔的组件,专门作为分隔线。而且还能使用索引进行个性化设计

代码语言:javascript
复制
var data = <PoemItem>[];
for (var i = 0; i < 20; i++) {
  data.add(PoemItem(
      image: AssetImage("images/wy_200x300.jpg"),
      title: "$i:以梦为马",
      author: "海子",
      summary: "我要做远方的忠诚的儿子,和物质的短暂情人,和所有以梦为马的诗人一样,我不得不和烈士和小丑走在同一道路上"));
}
var show = ListView.separated(
    padding: EdgeInsets.all(8.0),
    itemCount: data.length, //条目的个数
    itemBuilder: (BuildContext context, int index) {
      return PoemItemView(//数据填充条目
        data: data[index],
        onItemClickListener: () {//事件响应
          print(index);
        },
      );
    },
    separatorBuilder: (BuildContext context, int index) {
  return Padding(padding: EdgeInsets.only(left: 90),child: Divider(height: 1,color: Colors.orangeAccent,),);
},
    );
复制代码

2.4:一个ListView中不同的条目样式。

在抽取条目时,可以定义一个type属性,条目样式由Widget自身决定。

代码语言:javascript
复制
var random = Random();
var data = <ChartItem>[];
var strs = [
  "我是要成为编程之王的男人,你是要成为编程之王的女人",
  "凭君莫话封侯事,一将功成万骨枯。你觉得如何?",
  "在苍茫的大海上,狂风卷积着乌云,在乌云和大海之间,海燕像黑色的闪电,在高傲的飞翔。"
];
for (var i = 0; i < 20; i++) {
  data.add(ChartItem(
      headIcon: AssetImage(
          i.isEven ? "images/wy_200x300.jpg" : "images/icon_head.png"),
      text: strs[random.nextInt(strs.length)],
      type: i.isEven ? ChartType.left : ChartType.right));
}
var show = ListView.builder(
  itemCount: data.length, //条目的个数
  itemBuilder: (BuildContext context, int index) {
    return ChartWidget(//数据填充条目
      chartItem: data[index],
    );
  },
);

比如这里的ChartItem,本身定义了ChartType,在实现ChartWidget的时候,根据类型进行生成相应Widget,从而达到多种样式的效果。

代码语言:javascript
复制
enum ChartType { right, left }

class ChartItem {
  ImageProvider headIcon;
  double maxWith;
  ChartType type;
  String text;

  ChartItem({this.headIcon, this.text,this.maxWith = 250,this.type=ChartType.right});
}

class ChartWidget extends StatelessWidget {
  final ChartItem chartItem;

  ChartWidget({Key key, this.chartItem}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    switch (chartItem.type) {
      case ChartType.right:
        return _buildRight();
        break;
      case ChartType.left:
        return _buildLeft();
        break;
    }
  }

3.ListView滑动控制器(上拉刷新和下拉更新)
3.1:滑动控制器ScrollController的使用
代码语言:javascript
复制
class _ListViewPageState extends State<ListViewPage> {
  ScrollController _scrollController = ScrollController();//定义变量及初始化

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(() {//添加监听
     print("滑动了:${_scrollController.position.pixels},
     离顶部高:${_scrollController.position.maxScrollExtent}");
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();//销毁控制器
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
   //略同...
    var show = ListView.builder(
        controller: _scrollController,  //使用ScrollController
          //略同...
        );
  }
}
复制代码

3.2:上拉刷新

内置组件:RefreshIndicator,包裹一下即可

代码语言:javascript
复制
  return RefreshIndicator(child: show, onRefresh: _onRefresh//使用RefreshIndicator
}

bool isLoading = false;
Future<void> _onRefresh() async {//下拉刷新,异步延迟三秒
  if (isLoading) {
    return;
  }
  await Future.delayed(Duration(seconds: 3), () {
    setState(() {
      isLoading = false;
    });
  });
}

3.3:下拉加载更多
代码语言:javascript
复制
_scrollController.addListener(() {
  if (_scrollController.position.pixels ==//说明滑到底部
      _scrollController.position.maxScrollExtent) {
    _loadMore();
  }
});

bool isLoaded = false;

Future<void> _loadMore() async {
  await Future.delayed(Duration(seconds: 3), () {
    setState(() {
        isLoaded=true;
    });
  });
}

var show = ListView.builder(
    controller: _scrollController,
    itemCount: data.length + 1, //条目的个数
    itemBuilder: (BuildContext context, int index) {
      if (index == data.length) {
        return Offstage(//使用Offstage控制显隐
            offstage: isLoaded,
            child: Padding(
              padding: EdgeInsets.all(8.0),
              child: Center(
                child: CircularProgressIndicator(),
              ),
            ));
      } else {
        return ChartWidget(
          //数据填充条目
          chartItem: data[index],
        );
      }
    });

4. physics属性

physics对应ScrollPhysics类,其下有6个子类

  • FixedExtentScrollPhysics()NeverScrollableScrollPhysics
代码语言:javascript
复制
ListView无法滑动

  • PageScrollPhysics()
代码语言:javascript
复制
会根据你的滑动来自动调节,比如你滑的距离小,则自动还原,
到达一定大小,也会自动下滑一个条目

  • BouncingScrollPhysics()
代码语言:javascript
复制
顶底会有而外空间,让富有弹性

  • ClampingScrollPhysics()AlwaysScrollableScrollPhysics()
代码语言:javascript
复制
顶底会有蓝色阴影

另外还有reverse属性控制数据是否反序,scrollDirection控制ListView的方向

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年08月03日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.ListView 的基本使用
    • 1.1:三个构造
    • 2.ListView进阶使用
      • 2.1:完成条目的封装
        • 2.2:ListView的使用
          • 2.3:分隔线的添加
            • 2.4:一个ListView中不同的条目样式。
            • 3.ListView滑动控制器(上拉刷新和下拉更新)
              • 3.1:滑动控制器ScrollController的使用
                • 3.2:上拉刷新
                  • 3.3:下拉加载更多
                  • 4. physics属性
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档