城市选择器可以说是一个很常见的功能了,不过一直找不到一个顺手的现成的插件,无法根据自己的需求灵活的去创建。今天就根据我手上的需求自定义一个城市选择器。
首先推荐一个弹窗的插件flutter_custom_dialog: ^1.0.20
,用于实现城市选择器的底部弹出,具体的功能都在这个弹出层上实现。(文中只介绍城市选择实现思路,具体代码不一一赘述,文末放完整代码可自取运行)
实现过程
先来个模型
class CityResponse {
int id;
String name;
CityResponse({this.id, this.name});
}
有了模型后就可以创建列表了,几列的就创建几个(当你各个接口返回字段等不同时,可以创建不同的“CityResponse”)
List<CityResponse> provinceList = [];
List<CityResponse> cityList = [];
List<CityResponse> areaList = [];
有了列表后就可以渲染到UI上了,单列的选择器由CupertinoPicker.builder
创建,因为是三列,可以封装成一个组件,传入相应的数据等内容就可以渲染相应的列表了。
Widget buildCity(
{List<CityResponse> list,
FixedExtentScrollController scroll,
int columnNum,
Function onSelected}) {
return Expanded(
flex: 1,
child: Container(
height: 150,
child: list.length != 0
? CupertinoPicker.builder(
scrollController: scroll,
itemExtent: 30,
diameterRatio: 3,
squeeze: 0.8,
onSelectedItemChanged: (int _index) {
},
itemBuilder: (context, index) {
return Center(
child: Text(
"${list[index].name}",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600),
));
},
childCount: list.length,
)
: Container()),
);
}
通过row,即可产生三列选择器。
Row(
children: [
buildCity(
list: provinceList, scroll: scrollController[0],columnNum: 1),
buildCity(
list: cityList, scroll: scrollController[1],columnNum: 2),
buildCity(
list: areaList, scroll: scrollController[2],columnNum: 3),
],
)
此时的选择器各列之间没有关联,若想有关联,需要通过CupertinoPicker.builder
中的onSelectedItemChanged
方法实现。
onSelectedItemChanged:(index){}
选择时,会返回当前选择索引值。
在buildCity
中,为了判断是第几列,有传入columnNum
,因此,当第一列时:
if(columnNum == 1){
setState(() {
provinceIndex = _index;
cityIndex = 0;
areaIndex = 0;
cityList = getCity(id: _index);
areaList = getArea(id: getCity(id: _index)[0].id);
});
if (scrollController[1].hasClients) {
scrollController[1].jumpTo(0.0);
}
}
getCity(_index)
可以看做通过省id获取市列表的方法,getArea(id: getCity(id: _index)[0].id)
可以看做通过市id获取区列表的方法。这里需要注意的是,滑动的时候会频繁的请求,而网络请求会有延时,若前面请求的比后面的慢,则最新的会被前面的覆盖,因此需要进行处理。可以想办法减少无效请求次数,也可以在请求新的数据前先取消前一次请求,dio中有个参数为cancelToken,创建一个cancelToken传入,然后调用cancelToken.cancel()即可取消。
scrollController[1].jumpTo(0.0):
当第一列选择别的省时,市列表会重置,需要将是列表的滚动位置重置到0。
第二列时以此类推,根据相应列的需求进行获取数据等操作。比如第二列选择时只需要获取区列表数据即可,第三列选择则不需要获取新数据。
大致思路即是如此,具体的下载demo运行一下即一目了然。在实际使用中有什么问题可留言。
demo下载地址