Flutter实现省市区级联组件完整代码
在Flutter中实现轮子效果的省市区级联组件,当然也可以是任意的选择器,该Widget已经加入到ym_flutter_widget 0.0.2中,可以直接引入,你也可以拷贝下面的源码实现。
最终效果如图:
首先看下该组件的使用方法:
/// /// Cascader级联选择器 /// class CascaderPage extends StatefulWidget { CascaderPage({Key? key}) : super(key: key); final String title = "Cascader"; @override _CascaderPageState createState() => _CascaderPageState(); } class _CascaderPageState extends State
{ //显示底部弹窗 bool _showPickerDialog = false; //计算拼接地址字符串的 List _pickerSelected = [0,0,0]; String _address3 = "请选择"; //{"label": "请选择", "value": ""}, List > _regionData = [[],[],[]]; //数据 List
_regionValue = ["0","0","0"]; //默认值 @override void initState() { super.initState(); //加载数据 _loadData(0,0); } ///返回 Future _goBack() async{ Navigator.pop(context); } ///请求数据 Future _loadData(int pid,int index) async { List
下面是封装好的级联组件代码:
///
/// Cascader级联选择器
///
class YmCascader extends StatefulWidget {
//数据
late List> data;
//默认Value
late List value;
final double width;
final double height;
final Function onChanged;
final Function onOkClick;
final Function onCancelClick;
final Color backgroundColor;
final double itemHeight;
YmCascader(
this.data,
this.value,
{
Key? key,
required this.onChanged,
required this.onOkClick,
required this.onCancelClick,
this.itemHeight = 36,
this.backgroundColor = const Color(0xffffffff),
this.height = 150.0,
this.width = 150.0
}
): super(key: key);
@override
_YmCascaderState createState() => _YmCascaderState();
}
class _YmCascaderState extends State {
@override
void initState() {
super.initState();
}
Widget _getPickerWidget(int position){
double pickerItemWidth = (MediaQuery.of(context).size.width)/widget.data.length;
return YmPicker(
widget.data.elementAt(position),
widget.value[position],
width: pickerItemWidth,
itemHeight: 40,
height: 180,
onChanged: (index,val) {
print("Picker onChanged position=" + position.toString() + ",index=" + index.toString() + ",val=" + val);
widget.onChanged(position,index,val);
},
);
}
@override
Widget build(BuildContext context) {
return Container(
height:220,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children:[
Divider(
height: 1,
color: Color(0xffEFEFEF),
thickness: 1,
),
Container(
height:38,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
YmTextButton("取消", Color(0xFF666666), (){
widget.onCancelClick();
},isOutlined: true,size: Size(60,30),borderColor: Color(0x00666666),),
YmTextButton("确定", Color(0xFF3446F2), (){
widget.onOkClick();
},isOutlined: true,size:Size(60,30),borderColor: Color(0x00666666),),
]
),
),
Row(
children:List.generate(widget.data.length, (index) {
return _getPickerWidget(index);
}),
)
],
),
);
}
@override
void dispose() {
super.dispose();
}
}
///
/// 单个选择器picker
///
class YmPicker extends StatefulWidget {
//默认值
late String value;
//数据格式:{"label": "请选择", "value": ""}
late List data;
//前方文字
final String label;
final double width;
final double height;
final Function onChanged;
final double itemHeight;
final Color backgroundColor;
YmPicker(
this.data,
this.value,
{
Key? key,
this.label = "",
this.itemHeight = 36,
this.backgroundColor = const Color(0xffffffff),
this.height = 150,
this.width = 150,
required this.onChanged,
}
): super(key: key);
@override
_YmPickerState createState() => _YmPickerState();
}
class _YmPickerState extends State {
int _selectedIndex = 0;
//设置防抖周期为300毫秒
Duration durationTime = const Duration(milliseconds: 300);
Timer timer = Timer(Duration(milliseconds: 300), () {});
late FixedExtentScrollController controller;
@override
void initState() {
super.initState();
getDefaultValue();
controller = FixedExtentScrollController(initialItem: _selectedIndex);
}
// 获取默认选择值
getDefaultValue() {
for (var i = 0; i < widget.data.length; i++) {
if (widget.data[i]["value"] == widget.value) {
setState(() {
_selectedIndex = i;
});
break;
}
}
}
// 触发值改变
void _valueChanged(index) {
timer.cancel();
timer = new Timer(durationTime, () {
// 触发回调函数
print("values长度:" + widget.data.length.toString() + "-----" + index.toString());
widget.onChanged(index,widget.data[index]["value"]);
});
}
Widget _getItemWidget(int index,List items){
return Container(
alignment: Alignment.center,
height: widget.itemHeight,
child: Text(
items.elementAt(index)["label"],
style: TextStyle(
color: Color(0xff333333),
fontSize: 15,
height: 1.2,
fontWeight: FontWeight.w400,
),
),
);
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: widget.height,
width: widget.width,
child: CupertinoPageScaffold(
child: Container(
height: widget.height,
color: Colors.white,
child: Stack(
alignment: Alignment.center,
children: [
widget.label != "" ? Positioned(
top: widget.height / 2 - (widget.itemHeight / 2),
left: 18.0,
child: Container(
alignment: Alignment.center,
height: widget.itemHeight,
child: Text(
widget.label,
style: TextStyle(
color: Color(0xff333333),
fontSize: 15,
height: 1.2,
fontWeight: FontWeight.w500,
),
),
),
) : Offstage(offstage: true,),
CupertinoPicker.builder(
magnification: 1.0, // 整体放大率
scrollController:controller,
itemExtent: widget.itemHeight, // 所有子节点统一高度
useMagnifier: true, // 是否使用放大效果
backgroundColor: Colors.transparent,
childCount: widget.data.length,
onSelectedItemChanged: (int index) {
// 当选项改变时的回调
if (mounted) {
print('onSelectedItemChanged:$index');
_valueChanged(index);
}
},
itemBuilder: (BuildContext context, int index) {
return _getItemWidget(index,widget.data);
},
),
],
),
),
),
);
}
@override
void dispose() {
super.dispose();
timer.cancel();
}
}
本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。