fradio组件示例
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
var groupValue = '1';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const SizedBox(height: 35),
Text('自定义 Radio'),
const SizedBox(height: 10),
FRadio(
value: '1',
onChanged: (value) {},
groupValue: '0',
asCheckbox: true,
width: 80,
height: 30,
unselectedChild: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(width: 2, color: Colors.grey[300]),
borderRadius: BorderRadius.all(Radius.circular(5))),
child: Text(
'未选中',
style: TextStyle(color: Colors.redAccent),
),
),
selectedChild: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(width: 2, color: Colors.grey[300]),
borderRadius: BorderRadius.all(Radius.circular(6))),
child: Text(
'选中',
style: TextStyle(color: Colors.greenAccent),
),
),
),
const SizedBox(height: 35),
Text('Radio.style1'),
const SizedBox(height: 10),
Container(
padding: EdgeInsets.fromLTRB(12, 0, 12, 0),
margin: EdgeInsets.fromLTRB(12, 0, 12, 0),
decoration: BoxDecoration(
color: Color(0xffffAc500),
borderRadius: BorderRadius.all(Radius.circular(6))),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'快点击右侧 ✅ 试试啊!',
style: TextStyle(color: Colors.black),
),
FRadio.style1(
value: '2',
groupValue: '2',
onChanged: (value) {},
asCheckbox: true,
color: Colors.white,
),
],
),
),
const SizedBox(height: 35),
Text('Radio.style2'),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
Text(
'未选中状态',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style2(
value: '2',
groupValue: '0',
onChanged: (value) {},
asCheckbox: true,
),
],
),
Column(
children: <Widget>[
Text(
'选中状态',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style2(
value: '2',
groupValue: '2',
onChanged: (value) {},
asCheckbox: true,
),
],
),
Column(
children: <Widget>[
Text(
'不可用状态-选中',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style2(
value: '2',
groupValue: '2',
onChanged: (value) {},
asCheckbox: true,
enable: false,
),
],
),
Column(
children: <Widget>[
Text(
'不可用状态-未选中',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style2(
value: '2',
groupValue: '1',
onChanged: (value) {},
asCheckbox: true,
enable: false,
),
],
),
],
),
const SizedBox(height: 35),
Text('Radio.style3'),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
children: <Widget>[
Column(
children: <Widget>[
Text(
'未选中状态',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style3(
value: '2',
groupValue: '0',
onChanged: (value) {},
asCheckbox: true,
),
],
),
],
),
Column(
children: <Widget>[
Column(
children: <Widget>[
Text(
'选中状态',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style3(
value: '2',
groupValue: '2',
onChanged: (value) {},
asCheckbox: true,
),
],
),
],
),
Column(
children: <Widget>[
Column(
children: <Widget>[
Text(
'不可用状态-选中',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style3(
value: '2',
groupValue: '2',
onChanged: (value) {},
asCheckbox: true,
enable: false,
),
],
),
],
),
Column(
children: <Widget>[
Column(
children: <Widget>[
Text(
'不可用状态-未选中',
style: TextStyle(color: Colors.grey, fontSize: 10),
),
const SizedBox(height: 6),
FRadio.style3(
value: '2',
groupValue: '0',
onChanged: (value) {},
asCheckbox: true,
enable: false,
),
],
),
],
),
],
),
const SizedBox(height: 35),
Text('如何实现单选?'),
Text(
'通过一个公共变量 groupValue,可轻松实现单选!',
style: TextStyle(fontSize: 10),
),
const SizedBox(height: 10),
Container(
padding: EdgeInsets.fromLTRB(12, 0, 12, 0),
child: Column(
children: <Widget>[
Divider(
height: 0.5,
color: Colors.grey[300],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'标题0',
style: TextStyle(color: Colors.black),
),
FRadio.style1(
value: '0',
groupValue: groupValue,
onChanged: (value) {
setState(() {
groupValue = value;
});
},
asCheckbox: true,
),
],
),
Divider(
height: 0.5,
color: Colors.grey[300],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'标题1',
style: TextStyle(color: Colors.black),
),
FRadio.style1(
value: '1',
groupValue: groupValue,
onChanged: (value) {
setState(() {
groupValue = value;
});
},
asCheckbox: true,
),
],
),
Divider(
height: 0.5,
color: Colors.grey[300],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'标题2',
style: TextStyle(color: Colors.black),
),
FRadio.style1(
value: '2',
groupValue: groupValue,
onChanged: (value) {
setState(() {
groupValue = value;
});
},
asCheckbox: true,
),
],
),
Divider(
height: 0.5,
color: Colors.grey[300],
),
],
),
)
],
),
),
),
);
}
}
class FRadio<T> extends StatefulWidget {
final T value;
T groupValue;
final ValueChanged<T> onChanged;
bool asCheckbox = false;
Widget unselectedChild;
Widget selectedChild;
Widget disableChild;
bool enable = true;
double width;
double height;
T cacheGroupValue;
FRadio({
Key key,
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.width = 42,
this.height = 42,
this.enable = true,
this.asCheckbox = false,
this.unselectedChild,
this.selectedChild,
this.disableChild,
}) : cacheGroupValue = groupValue,
assert(unselectedChild != null && selectedChild != null),
assert(!(!enable && disableChild == null),
"The 'disableChild' param can't be null when 'enable=false'."),
super(key: key);
FRadio.style1({
Key key,
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.width = 42,
this.height = 42,
this.enable = true,
this.asCheckbox = false,
Color color,
}) : this.unselectedChild = Container(
color: Colors.transparent,
width: width,
height: height,
),
this.selectedChild = Container(
width: width,
height: height,
child: Icon(
Icons.check,
color: color ?? Color(0xffFCA500),
size: width.toDouble() / 42.toDouble() * 30.toDouble(),
),
),
this.disableChild = Container(
color: Colors.transparent,
width: width,
height: height,
),
super(key: key);
FRadio.style2({
Key key,
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.width = 42,
this.height = 42,
this.enable = true,
this.asCheckbox = false,
Color color,
}) : this.unselectedChild = Container(
decoration: BoxDecoration(
// 设置边框
border: Border.all(
width: width / 42 * 2, color: color ?? Color(0xffE0E0E0)),
// 设置圆角
borderRadius: BorderRadius.all(Radius.circular(width / 42 * 6))),
),
this.selectedChild = Container(
decoration: BoxDecoration(
color: Colors.white,
// 设置边框
border: Border.all(
width: width / 42 * 2, color: color ?? Color(0xffFCA500)),
// 设置圆角
borderRadius:
BorderRadius.all(Radius.circular(width / 42 * 6))),
child: Icon(
Icons.check,
color: color ?? Color(0xffFCA500),
size: width.toDouble() / 42.toDouble() * 30.toDouble(),
)),
this.disableChild = Container(
decoration: BoxDecoration(
color: Color(0xffE0E0E0),
// 设置边框
border:
Border.all(width: width / 42 * 2, color: Color(0xffCCCCCC)),
// 设置圆角
borderRadius: BorderRadius.all(Radius.circular(width / 42 * 6))),
child: value == groupValue
? Icon(
Icons.check,
color: Color(0xffCCCCCC),
size: width.toDouble() / 42.toDouble() * 30.toDouble(),
)
: null,
),
super(key: key);
FRadio.style3({
Key key,
@required this.value,
@required this.groupValue,
@required this.onChanged,
this.width = 42,
this.height = 42,
this.enable = true,
this.asCheckbox = false,
Color color1,
Color color2,
}) : this.unselectedChild = Container(
decoration: BoxDecoration(
// 设置边框
border: Border.all(
width: width / 42 * 2, color: color1 ?? Color(0xffFF9F02)),
// 设置圆角
borderRadius: BorderRadius.all(Radius.circular(width / 2))),
),
this.selectedChild = Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
color1 ?? Color(0xffFCD71E),
color2 ?? Color(0xffFF9F02)
]),
// 设置圆角
borderRadius: BorderRadius.all(Radius.circular(width / 2))),
child: Icon(
Icons.check,
color: Color(0xffffffff),
size: width.toDouble() / 42.toDouble() * 30.toDouble(),
)),
this.disableChild = Container(
decoration: BoxDecoration(
color: Color(0xffE0E0E0),
// 设置边框
border:
Border.all(width: width / 42 * 2, color: Color(0xffCCCCCC)),
// 设置圆角
borderRadius: BorderRadius.all(Radius.circular(width / 2))),
child: value == groupValue
? Icon(
Icons.check,
color: Color(0xffCCCCCC),
size: width.toDouble() / 42.toDouble() * 30.toDouble(),
)
: null,
),
super(key: key);
@override
State<StatefulWidget> createState() {
return _Radio<T>();
}
}
class _Radio<T> extends State<FRadio<T>> {
bool get _enabled => widget.enable && widget.onChanged != null;
bool get _selected => widget.value == widget.groupValue;
_handOnTap() {
if (widget.asCheckbox) {
setState(() {
if (widget.groupValue == widget.value) {
widget.groupValue = widget.cacheGroupValue;
} else {
widget.groupValue = widget.value;
}
});
}
widget.onChanged(widget.value);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _enabled ? _handOnTap : null,
child: Container(
// color: Colors.grey,
width: widget.width,
height: widget.height,
child: _buildChild(),
),
);
}
_buildChild() {
if (widget.enable) {
return _selected ? widget.selectedChild : widget.unselectedChild;
} else {
return widget.disableChild;
}
}
}