Flutter学习(8)——CheckBox多选框使用及动态更改多选框数据
原文地址:Flutter学习(8)——CheckBox多选框使用及动态更改多选框数据 | Stars-One的杂货小窝
最近项目需求需要调整页面,记录一下实现过程
这次主要是要实现个评价页面,选择不同的星级显示不同的多选框数据,加上之前也没有使用过CheckBox,今天便是一起讲吧
效果预览

效果看似有点复杂,我们一步步来实现吧
1.星级组件使用
首先,我们有使用到星级评分组件 在pubspec.yaml文件中添加下面依赖
flutter_simple_rating_bar: ^0.0.3
使用的话页面也是有个例子介绍,我们直接拿来即可使用
RatingBar(
//默认选择5星
rating: 5,
//总星星数目
starCount: 5,
//星星图标
icon: Icon(
Icons.star,
size: 40,
color: Colors.grey,
),
spacing: 5.0,
size: 40,
isIndicator: false,
//是否可选半星
allowHalfRating: true,
onRatingCallback:(double value, ValueNotifier<bool> isIndicator) {
//value是点击后选中的星星数(即评分),范围为1-rating(我们上面rating为5)
},
color: Colors.amber,
)
现在我们要根据选择的数目不同,从而显示不同的文字,这过程是动态的,所以我们选择使用StatefulWidget作为页面继承的基类
我们先在State类中加上相应的数据,如下所示
//显示的文字信息
List typeList = ["非常不满意", "不满意", "基本满意", "满意", "非常满意"];
//当前选择type的下标
int selectType = 4;
我们文字显示内容是typeList[selectType],我们在星级评分选择的回调函数,更改selecType即可实现更改UI的功能
Column(
children: [
RatingBar(
rating: 5,
//默认选择5星
starCount: 5,
//总星星数目
//星星图标
icon: Icon(
Icons.star,
size: 40,
color: Colors.grey,
),
spacing: 5.0,
size: 40,
isIndicator: false,
//是否可选半星
allowHalfRating: true,
onRatingCallback:
(double value, ValueNotifier<bool> isIndicator) {
//更改数据同时也要更改UI,所以使用setState方法
setState(() {
//注意 星级从1开始,selectType是下标,从0开始,需要减1
selectType = value.toInt() - 1;
});
},
color: Colors.amber,
),
//取指定下标的文字内容展示
Text(typeList[selectType])
],
)
2.多选框使用及数据更改
CheckBox多选框的使用需要定义一个bool类型的数据,每次点击需要更改此数据来改变CheckBox的选择状态
由于我们是使用的列表数据,所以每个数据写个变量不太现实,而且繁琐,所以可以考虑在实体类中加个bool类型的字段,用来存储CheckBox选择的状态
这里,数据我就暂且写死,实际上是要通过调用接口获取的
void initTagData() {
var data = """{
"code":200,
"error":"",
"ReturnValue":[{"generalstars":"1","tagid":"109759610348409856","tagname":"无理由超过法定办理时间","updatetime":"2020-06-12 17:38:00"},{"generalstars":"1","tagid":"6176177900787350","tagname":"在办事指南之外增加新的审批条件","updatetime":"2020-08-27 00:00:00"},{"generalstars":"1","tagid":"6176177900787351","tagname":"需提供办事指南之外的申报材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"1","tagid":"7176177890787535","tagname":"无理由超过法定办理时间","updatetime":"2020-08-27 00:00:00"},{"generalstars":"2","tagid":"6176177900787349","tagname":"未在承诺时间内办结","updatetime":"2020-08-27 00:00:00"},{"generalstars":"2","tagid":"6176177900787347","tagname":"没有提供材料样本","updatetime":"2020-08-27 00:00:00"},{"generalstars":"2","tagid":"6176177900787348","tagname":"没有提供材料清单","updatetime":"2020-08-27 00:00:00"},{"generalstars":"3","tagid":"119596473292723200","tagname":"22222","updatetime":"2020-06-12 17:38:00"},{"generalstars":"3","tagid":"6176177900787346","tagname":"在承诺的时间内办结","updatetime":"2020-08-27 00:00:00"},{"generalstars":"3","tagid":"6176177900787345","tagname":"提供申报材料样本","updatetime":"2020-08-27 00:00:00"},{"generalstars":"3","tagid":"6176177900787344","tagname":"一次性告知需要补正的材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"4","tagid":"6176177900787340","tagname":"填写一张表单就可以完成申报","updatetime":"2020-08-27 00:00:00"},{"generalstars":"4","tagid":"6176177900787341","tagname":"在线提交材料窗口核验","updatetime":"2020-08-27 00:00:00"},{"generalstars":"4","tagid":"6176177900787342","tagname":"一张清单告知全部申报材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"5","tagid":"7176177890787335","tagname":"一窗受理一次办结","updatetime":"2020-08-27 00:00:00"},{"generalstars":"5","tagid":"7176177890787235","tagname":"可以先受理后补材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"5","tagid":"7176177890787435","tagname":"不用提交证明","updatetime":"2020-08-27 00:00:00"}]
}""";
Map<String, dynamic> responseData = jsonDecode(data);
var tagListModel = TagListModel.fromJson(responseData);
if (tagListModel.code == 200) {
//注意要使用setState,才会使UI发生变化(因为网络请求是耗时任务,可能界面渲染完毕后才能请求到数据)
setState(() {
tagList.addAll(tagListModel.tagItems);
});
}
}
TagListModel是生成的实体类,生成的步骤已经在上篇文章讲解到,这里就不在赘述了
按照上面说的思路,我们在TagListModel的实体类中(其实是在TagItem中),添加一个bool类型的字段,用来作为存储CheckBox选择的状态,
这里使用插件生成的实体类(TagListModel里面还包含有个实体类),原本应该是ReturnValue,但为了方便,我将其改了个名字TagItem

Flutter中的CheckBox是只有一个框,并不包含文字,所以我们得组合一个文本,拼成一个Widget,_tagView()这个方法就是每个选项
Widget _tagView(item) {
var str = item.tagname;
return InkWell(
child: Row(
children: <Widget>[
Checkbox(
value: item.flag,
activeColor: Colors.blue,
onChanged: (bool val) {
// val 是布尔值
this.setState(() {
item.flag = val;
});
},
),
Text(str),
],
),
onTap: () {
setState(() {
item.flag = !item.flag;
});
},
);
这里最外层使用了InkWell,是因为其有onTag的点击事件方法 点击整行都可以去改变CheckBox的状态,用户体验比较友好,如果没有的话,只能点击CheckBox的框来改变状态
有了上面的一个子项,现在我们需要构建一个多选选项列表(列表包含N个_tagView组件)
先声明两个数组,用来存放数据
//标签数据(存放所有数据)
List<TagItem> tagList = [];
//临时存放的数据,后面评价提交需要
List<TagItem> tempTagList = [];
这里为什么需要两个数组呢?
主要是考虑到后面需要获取勾选的数据,所以才考虑再多加一个临时的列表
每次改变星级的时候,列表选项的数据就会改变,之后我们只需要去这个临时列表中筛选状态为true的数据即可
List<Widget> _tagList() {
List<Widget> widgetList = [];
var list = this.tagList;
tempTagList.clear();
var star = selectType.toInt() + 1;
//匹配相同星级数据
for (var i = 0; i < list.length; i++) {
var item = list[i];
if (item.generalstars == star.toString()) {
//存在临时表中,之后可以快速查找用户的选择
tempTagList.add(item);
var row = _tagView(item);
widgetList.add(row);
}
}
return widgetList;
}
由于数据较少,可以使用Column用来包裹上面的组件_tagList
//标签选项
Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.fromLTRB(10, 0, 15, 5),
child: Column(
children: _tagList(),
)
)
由于提交标签需要传标签的id,而且需要逗号隔开,所以需要遍历临时选项列表,处理一下即可
//处理标签
var tagId = "";
for (var i = 0; i < tempTagList.length; i++) {
var item = tempTagList[i];
//查找选择的标签数据
if (item.flag) {
tagId += item.tagid + ",";
}
}
if (tagId.length>0) {
tagId = tagId.substring(0, tagId.length - 1);
}
print(tagId);
源码
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_demo/model/tag_list_model.dart';
import 'package:flutter_simple_rating_bar/flutter_simple_rating_bar.dart';
class CheckBoxPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new CheckBoxState();
}
}
class CheckBoxState extends State<CheckBoxPage> {
//标签数据
List<TagItem> tagList = [];
//临时标签,后面评价提交需要
List<TagItem> tempTagList = [];
List typeList = ["非常不满意", "不满意", "基本满意", "满意", "非常满意"];
//当前选择type的下标
int selectType = 4;
@override
void initState() {
//初始化数据(这里是暂时写死,实际中这里是调用接口)
initTagData();
}
void initTagData() {
var data = """{
"code":200,
"error":"",
"ReturnValue":[{"generalstars":"1","tagid":"109759610348409856","tagname":"无理由超过法定办理时间","updatetime":"2020-06-12 17:38:00"},{"generalstars":"1","tagid":"6176177900787350","tagname":"在办事指南之外增加新的审批条件","updatetime":"2020-08-27 00:00:00"},{"generalstars":"1","tagid":"6176177900787351","tagname":"需提供办事指南之外的申报材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"1","tagid":"7176177890787535","tagname":"无理由超过法定办理时间","updatetime":"2020-08-27 00:00:00"},{"generalstars":"2","tagid":"6176177900787349","tagname":"未在承诺时间内办结","updatetime":"2020-08-27 00:00:00"},{"generalstars":"2","tagid":"6176177900787347","tagname":"没有提供材料样本","updatetime":"2020-08-27 00:00:00"},{"generalstars":"2","tagid":"6176177900787348","tagname":"没有提供材料清单","updatetime":"2020-08-27 00:00:00"},{"generalstars":"3","tagid":"119596473292723200","tagname":"22222","updatetime":"2020-06-12 17:38:00"},{"generalstars":"3","tagid":"6176177900787346","tagname":"在承诺的时间内办结","updatetime":"2020-08-27 00:00:00"},{"generalstars":"3","tagid":"6176177900787345","tagname":"提供申报材料样本","updatetime":"2020-08-27 00:00:00"},{"generalstars":"3","tagid":"6176177900787344","tagname":"一次性告知需要补正的材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"4","tagid":"6176177900787340","tagname":"填写一张表单就可以完成申报","updatetime":"2020-08-27 00:00:00"},{"generalstars":"4","tagid":"6176177900787341","tagname":"在线提交材料窗口核验","updatetime":"2020-08-27 00:00:00"},{"generalstars":"4","tagid":"6176177900787342","tagname":"一张清单告知全部申报材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"5","tagid":"7176177890787335","tagname":"一窗受理一次办结","updatetime":"2020-08-27 00:00:00"},{"generalstars":"5","tagid":"7176177890787235","tagname":"可以先受理后补材料","updatetime":"2020-08-27 00:00:00"},{"generalstars":"5","tagid":"7176177890787435","tagname":"不用提交证明","updatetime":"2020-08-27 00:00:00"}]
}""";
Map<String, dynamic> responseData = jsonDecode(data);
var tagListModel = TagListModel.fromJson(responseData);
if (tagListModel.code == 200) {
//注意要使用setState,才会使UI发生变化(因为网络请求是耗时任务,可能界面渲染完毕后才能请求到数据)
setState(() {
tagList.addAll(tagListModel.tagItems);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("评价"),
),
body: Column(
children: [
Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.fromLTRB(15, 0, 15, 10),
child: Wrap(
spacing: 10,
children: [
Center(
child: Column(
children: [
RatingBar(
rating: 5,
//默认选择5星
starCount: 5,
//总星星数目
//星星图标
icon: Icon(
Icons.star,
size: 40,
color: Colors.grey,
),
spacing: 5.0,
size: 40,
isIndicator: false,
//是否可选半星
allowHalfRating: true,
onRatingCallback:
(double value, ValueNotifier<bool> isIndicator) {
//更改数据同时也要更改UI,所以使用setState方法
setState(() {
//注意 星级从1开始,selectType是下标,从0开始,需要减1
selectType = value.toInt() - 1;
});
},
color: Colors.amber,
),
_tipText()
],
),
)
],
),
),
//标签选项
Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.fromLTRB(10, 0, 15, 5),
child: Column(
children: _tagList(),
)),
Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.fromLTRB(10, 0, 15, 5),
child: FlatButton(
child: Text("提交"),
onPressed: () {
//处理标签
var tagId = "";
for (var i = 0; i < tempTagList.length; i++) {
var item = tempTagList[i];
//查找选择的标签数据
if (item.flag) {
tagId += item.tagid + ",";
}
}
if (tagId.length>0) {
tagId = tagId.substring(0, tagId.length - 1);
}
print(tagId);
},
)),
],
),
);
}
Widget _tipText() {
//根据selectType变更UI
return Text(typeList[selectType]);
}
List<Widget> _tagList() {
List<Widget> widgetList = [];
var list = this.tagList;
tempTagList.clear();
var star = selectType.toInt() + 1;
for (var i = 0; i < list.length; i++) {
var item = list[i];
if (item.generalstars == star.toString()) {
//存在临时表中,之后可以快速查找用户的选择
tempTagList.add(item);
var row = _tagView(item);
widgetList.add(row);
}
}
return widgetList;
}
Widget _tagView(item) {
var str = item.tagname;
return InkWell(
child: Row(
children: <Widget>[
Checkbox(
value: item.flag,
activeColor: Colors.blue,
onChanged: (bool val) {
// val 是布尔值
this.setState(() {
item.flag = val;
});
},
),
Text(str),
],
),
onTap: () {
setState(() {
item.flag = !item.flag;
});
},
);
}
}
Flutter学习(8)——CheckBox多选框使用及动态更改多选框数据的更多相关文章
- 组合框里添加复选框的方法(使用勾选的假象,用图片代替而已,并非QT原生支持)
组合框可以看作是列表框和文本框的组合,因其占据的空间少,使用操作方便,常被界面设计人员用于界面开发设计中,在有限个输入的条件下,组合框常用来代替文本框,这样从用户使用角度来看,更趋人性化,所见即所得. ...
- Js动态添加复选框Checkbox
Js动态添加复选框Checkbox的实例方法!!! 首先,使用JS动态产生Checkbox可以采用如下类似的语句: var checkBox=document.createElement(" ...
- Flutter学习笔记(21)--TextField文本框组件和Card卡片组件
如需转载,请注明出处:Flutter学习笔记(21)--TextField文本框组件和Card卡片组件 今天来学习下TextField文本框组件和Card卡片组件. 只要是应用程序就少不了交互,基本上 ...
- Flutter学习笔记(13)--表单组件
如需转载,请注明出处:Flutter学习笔记(13)--表单组件 表单组件是个包含表单元素的区域,表单元素允许用户输入内容,比如:文本区域,下拉表单,单选框.复选框等,常见的应用场景有:登陆.注册.输 ...
- jquery控制动态生成的gridview中多列checkbox的全选反选及自动判断是否全选状态
动态生成的Gridview的前台html代码如下: <table class="usertableborder" cellspacing="0" ...
- checkbox属性checked="checked"但状态不是勾选状态的解决办法
原因: jQuery API明确说明,1.6+的jQuery要用prop,不能用attr否则无效,尤其是checkBox的checked的属性的判断.
- php处理表单中的复选框问题以及js实现全选
做的一个项目中遇到了全选和取消全选的问题,这是一个很普遍的功能,,虽然我们经常用到,但是真正做起来却发现行不通,在网上找了些,大部分都是ie,但是谷歌内核浏览器不能正常实现,所以经过小小的调整,今天就 ...
- 【jQuery】复选框的全选、反选,推断哪些复选框被选中
本文与<[JavaScript]复选框的全选.反选.推断哪些复选框被选中>(点击打开链接)为姊妹篇,把里面内容再与jQuery框架中实现一次,相同做到例如以下的效果: 布局还是相同的布局, ...
- springMvc接收ajax数组参数,以及jquery复选框选中、反选、全选、全不选
一.复选框选中.反选.全选.全不选 html代码: <input type='checkbox' name='menuCheckBox' value='10' >苹果 <input ...
随机推荐
- 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法
什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...
- Windows10上基于Visual Studio Code安装Golang开发环境
GoLang简介 Go编程语言是一个开源项目,它使程序员更具生产力. Go语言具有很强的表达能力,它简洁.清晰而高效.得益于其并发机制,用它编写的程序能够非常有效地利用多核与联网的计算机,其新颖的类型 ...
- 66.QT-线程并发、QTcpServer并发、QThreadPool线程池
1.线程并发一个程序内部能拥有多个线程并行执行.一个线程的执行可以被认为是一个CPU在执行该程序.当一个程序运行在多线程下,就好像有多个CPU在同时执行该程序.总之,多线程即可以这么理解:多线程是处理 ...
- [HNOI2006]公路修建问题题解
题目 题目描述 OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多.然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕.所以,OIER Association组织成立了, ...
- mapboxgl 互联网地图纠偏插件(二)
前段时间写的mapboxgl 互联网地图纠偏插件(一)存在地图旋转时瓦片错位的问题. 这次没有再跟 mapboxgl 的变换矩阵较劲,而是另辟蹊径使用 mapboxgl 的自定义图层,重新写了一套加载 ...
- UVA 10689 Yet another Number Sequence 矩阵快速幂 水呀水
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...
- Redis 底层数据结构之字典
文章参考 <Redis 设计与实现>黄建宏 字典 在字典中,每个键都是独一无二的,程序可以在字典中根据键查找与之相关联的值,或者通过键来更新和删除值. 字典在 Redis 中的应用相当广泛 ...
- 使用Vue-Cli搭建Ant Design Vue前端开发环境
如果文章有帮助到你,还请点个赞或留下评论 搭建脚手架 环境准备 nodeJS vue-cli 如果没有安装点击此处查看安装方法 进入 vue ui 1.打开终端,输入命令 vue ui 2.选择项目存 ...
- CentOS-Docker安装phpMyAdmin(MySQL的web客户端)
注:phpMyAdmin是一款MySQL的web客户端,还是很直观且好用的,所以推荐给你~ 下载镜像 $ docker pull phpmyadmin/phpmyadmin 运行镜像 1.无指定固定数 ...
- SpringBoot:Sqlite3+SpringBoot2.1.3+Mybatis-Puls整合项目
应公司要求完成sqlite3数据库的增改查小功能,特此记录一下. 1.建造项目 结构如下 因为是提供给前端调用所以做了接口. 2.Pom依赖文件 下面是这个项目所依赖的jar包. <parent ...