文章目录
- 1. 概念介绍
- 2. 思路与方法
- 2.1 实现思路
- 2.2 实现方法
- 3. 代码与效果
- 3.1 示例代码
- 3.2 运行效果
- 4. 内容总结
我们在上一章回中介绍了"如何给图片添加阴影"相关的内容,本章回中将介绍自定义Radio组件.闲话休提,让我们一起Talk Flutter吧。
1. 概念介绍
我们在前面章回中介绍过Radio组件相关的知识,本章回中介绍的Radio和官方提供的Radio在功能上相同,只是官方提供的Radio不支持修改外观,所以我们准备重新
定义Radio组件。本章回中将详细介绍自定义Radio组件的思路和方法。
2. 思路与方法
2.1 实现思路
最开始想继承Radio组件,然后在此基础上修改外观,后来发来这个思路行不通,因为Radio组件没有提供child属性,即使继承后也无法修改它的内容。因此我们准备
通过组合其它组件来实现自定义Radio组件。Radio上的文本通过Text组件实现,是否被选择的状态通过checkBox组件实现。把这两个组件通过Row组合成一行就是一
个Radio组件。当然了,如果想添加图片的话可以在Row中添加Image组件。有了外观后还需要实现单选功能,就是说多个Radio放在一起使用时有且只有一个Radio能
被选择。我们通过索引id和组件id来实现这个功能,如果这两个id相等,那么当前Radio处于被选择状态,反之处于末选择状态。索引值是固定的,通常不能修改,因此
我们提供一个修改组件id的方法,在点击Radio时通过该方法来修改组id.
2.2 实现方法
自定义Radio的思路介绍完了,不过有看官说感觉有点抽象,接下来我们将介绍详细的实现方法:
- 创建一个StatefulWidget组件,该组件表示单个Radio;
- 在StatefulWidget组件的参数中添加两个必选参数当作索引id和组id;
- 提供一个修改参数的方法,把该方法放到StatefulWidget组件的参数中,相当于向外开放;
- 在StatefulWidget组件中添加Text和CheckBox组件,并且通过Row把它们组合在一起;
- 在Row组件外层添加Listener组件,也可以换成手势组件,主要用来响应点击事件;
- 当点击事件发生时调用修改参数的方法,并且把当前Radio的索引id通过方法的参数传递到外面;
- 再StatefulWidget组件外实现修改组id的方法,主要是把组件id修改成当前Radio的索引id;
- 在StatefulWidget组件中判断组id和索引id是否相同,如果相同,把CheckBox修改为选择状态;
上面介绍的实现方法中比较难理解的单选功能,该功能的核心在于在单个Radio中响应点击事件,同时把修改组id的方法向外开放,在单个Radio组件修改组id时刷新所
有Radio组件的状态,这时被选择的组件会因为组id和索引id相等显示被选择状态,其它Radio组件则因为组id和索引id不相等显示末选择状态。
3. 代码与效果
3.1 示例代码
typedef ItemSelected<T> = void Function(T value);
///单个Radio组件
class MutexWidget extends StatefulWidget {
MutexWidget({super.key,required this.groupValue, required this.index,
required this.itemSelected,
});
///索引id和组id,以及修改组id的方法都写成组件的属性
int groupValue;
int index;
ItemSelected<int> itemSelected;
State<MutexWidget> createState() => _MutexWidgetState();
}
class _MutexWidgetState extends State<MutexWidget> {
bool isWidgetSelected = false;
Widget build(BuildContext context) {
///如果这两个id相等,那么当前Radio处于被选择状态,反之处于末选择状
if (widget.index == widget.groupValue) {
isWidgetSelected = true;
} else {
isWidgetSelected = false;
}
///组件的外观在这里,可以自定义
return Listener(
onPointerDown: (event) {
if (widget.index == widget.groupValue) {
isWidgetSelected = true;
} else {
isWidgetSelected = false;
}
widget.itemSelected(widget.index);
},
child: Container(
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(30),
),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("Item ${widget.index}"),
Checkbox(
activeColor: Colors.blue,
side: const BorderSide(
width: 3, color: Colors.grey,),
shape: const CircleBorder(),
value: isWidgetSelected,
onChanged: (value) {},)
],
),
),
);
}
}
///使用多个组件,主要是实现修改组id的方法,同时使用setState方法刷新所有组件的状态
child: ListView(
children: [
MutexWidget(groupValue: groupId, index:1, itemSelected: (v){
setState(() {
groupId = v;
});
}),
const SizedBox(height: 16,),
MutexWidget(groupValue: groupId, index:2, itemSelected: (v){
setState(() {
groupId = v;
});
}),
const SizedBox(height: 16,),
MutexWidget(groupValue: groupId, index:3, itemSelected: (v){
setState(() {
groupId = v;
});
}),
const SizedBox(height: 16,),
MutexWidget(groupValue: groupId, index:4, itemSelected: (v){
setState(() {
groupId = v;
});
}),
const SizedBox(height: 16,),
MutexWidget(groupValue: groupId, index:5, itemSelected: (v){
setState(() {
groupId = v;
});
}),
const SizedBox(height: 16,),
],
),
上面的示例代码中包含两个部分,一部分是单个Radio组件的代码,另外一部分是使用多个Radio组件的代码,代码完全按照上一小节中的实现方法来编写,并且在关键
位置添加了注释,这样有助于大家理解代码。
3.2 运行效果
编译并且运行上面小节中的代码,可以得到下面的运行效图。图中显了个五个Radio组件,它们形成一组Radio,这组Radio中有且只有一个Radio能被选择,也就是我
们常用的单选功能。此外,单个Radio组件的布局,内容,以及颜色等风格可以依据需要自行修改。
4. 内容总结
最后,我们对本章回中的内容做一个全面的总结:
- 官方提供的Radio组件无法修改外观,我们可以通过自定义Radio来实现;
- 自定义Radio组件的外观通过使用Row组件组合Text组件和CheckBox组件实现;
- 自定义Radio组件的难点在于实现单选功能,它需要在Radio组件内部和外部一起实现;
- 自定义Radio组件的内容,布局和颜色等风格可以自行设计与实现,实现方法可以参考示例代码中Row部分的代码;
看官们,与"自定义Radio组件"相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!