taiwan_city_picker 1.0.2
taiwan_city_picker: ^1.0.2 copied to clipboard
A Flutter widget for Taiwan city and district picker.
Taiwan City Picker #
台灣縣市選擇器,可以自訂樣式。
Features #
- 設定座標由近到遠顯示
- 縣市區黑名單、白名單控制顯示
- 大小寫臺、台切換
- 選項顯示郵遞區號
- 英文語系
- 文字輸入搜尋
- 框線樣式設定
- 水平和垂直佈局
- 自訂 Builder
- 提供 Controller 控制器
Options #
基本設定 #
| Option | Description | Type | Default |
|---|---|---|---|
controller |
控制選擇狀態 | TaiwanCityPickerController? |
null |
onChange |
選擇變更時的 Callback Function | Function? |
null |
countyHint |
縣市選擇器的提示文字 | String? |
null |
districtHint |
地區選擇器的提示文字 | String? |
null |
onlyCounty |
是否只顯示縣市選擇器 | bool |
false |
Layout #
| Option | Description | Type | Default |
|---|---|---|---|
layoutDirection |
Layout 方向 | LayoutDirection |
horizontal |
mainAxisAlignment |
主軸對齊方式 | MainAxisAlignment |
start |
crossAxisAlignment |
副軸對齊方式 | CrossAxisAlignment |
center |
mainAxisSize |
主軸大小 | MainAxisSize |
max |
spacing |
縣市和地區選擇器之間的間距 | double |
12.0 |
Style #
| Option | Description | Type | Default |
|---|---|---|---|
border |
輸入框邊框樣式 | InputBorder? |
null |
menuHeight |
下拉選單的最大高度 | double |
200.0 |
功能設定 #
| Option | Description | Type | Default |
|---|---|---|---|
searchable |
是否啟用搜尋功能 | bool |
false |
language |
顯示語言(中文/英文) | Language |
zhTW |
showZipCode |
是否在地區名稱前顯示郵遞區號 | bool |
false |
stdWord |
是否使用標準字(true: 臺,false: 台) | bool |
true |
Location #
| Option | Description | Type | Default |
|---|---|---|---|
latitude |
參考點緯度(用於距離排序) | double? |
null |
longitude |
參考點經度(用於距離排序) | double? |
null |
Filter #
| Option | Description | Type | Default |
|---|---|---|---|
whitelistCountyCode |
縣市代碼白名單 | List<String>? |
null |
blacklistCountyCode |
縣市代碼黑名單 | List<String>? |
null |
whitelistZipCode |
郵遞區號白名單 | List<int>? |
null |
blacklistZipCode |
郵遞區號黑名單 | List<int>? |
null |
Default Value #
| Option | Description | Type | Default |
|---|---|---|---|
defaultCountyCode |
預設選擇的縣市代碼 | String? |
null |
defaultZipCode |
預設選擇的郵遞區號 | int? |
null |
Custom UI Builder #
| Option | Description | Type | Default |
|---|---|---|---|
countyBuilder |
自訂縣市選擇器 UI | CountyBuilder? |
null |
districtBuilder |
自訂地區選擇器 UI | DistrictBuilder? |
null |
layoutBuilder |
自訂整體佈局 | LayoutBuilder? |
null |
使用範例 #
基本使用 #

TaiwanCityPicker(
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {
print('changeType: $changeType');
print('county: $county');
print('district: $district');
},
)
Vertical (垂直 Layout) #

TaiwanCityPicker(
layoutDirection: LayoutDirection.vertical,
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Custom Border (框線設定) #

TaiwanCityPicker(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.blue, width: 2),
),
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Location Sorting (距離由近到遠排序) #

TaiwanCityPicker(
latitude: 24.0541621, // 台中市緯度
longitude: 120.6478417, // 台中市經度
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Whitelist Zip Code (只顯示樹林、龜山) #

TaiwanCityPicker(
whitelistZipCode: [238, 333], // 樹林區、龜山區
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Blacklist County (不顯示外島縣市) #

TaiwanCityPicker(
blacklistCountyCode: ['09007', '10016', '09020'], // 金門、連江、澎湖
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Variant Chinese characters (異體字) #

TaiwanCityPicker(
defaultZipCode: 950,
stdWord: false,
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Default County Code (預設臺中市) #

TaiwanCityPicker(
defaultCountyCode: '66000', // 臺中市代碼
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Default Zip Code (預設信義區 110) #

TaiwanCityPicker(
defaultZipCode: 110, // 信義區郵遞區號
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Searchable Mode #

TaiwanCityPicker(
searchable: true, // 啟用搜尋功能
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Controller Methods (控制器操作) #

final TaiwanCityPickerController controller = TaiwanCityPickerController();
TaiwanCityPicker(
controller: controller,
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
ElevatedButton(
onPressed: () => controller.setCountyCode('64000'),
child: Text('設定高雄市'),
),
ElevatedButton(
onPressed: () => controller.setZipCode(238),
child: Text('設定樹林區'),
),
ElevatedButton(
onPressed: () => controller.reset(),
child: Text('清空'),
),
English Mode (英文) #

TaiwanCityPicker(
layoutDirection: LayoutDirection.vertical,
language: Language.enUS,
showZipCode: true,
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Only County (只需要縣市選擇) #

TaiwanCityPicker(
onlyCounty: true,
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)
Custom Builder 1 (自訂樣式 1) #

TaiwanCityPicker(
countyBuilder:
(
BuildContext context,
List<TaiwanCityModel> counties,
TaiwanCityModel? selectedCounty,
void Function(TaiwanCityModel?) onCountySelected,
String hintText,
) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.blue, Colors.lightBlue]),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Padding(
padding: EdgeInsets.all(12),
child: Icon(Icons.location_city, color: Colors.white),
),
Expanded(
child: DropdownButton<TaiwanCityModel>(
value: selectedCounty,
hint: Text(hintText, style: TextStyle(color: Colors.white)),
isExpanded: true,
underline: SizedBox.shrink(),
dropdownColor: Colors.blue,
items: counties.map((county) {
return DropdownMenuItem<TaiwanCityModel>(
value: county,
child: Text(county.countyName, style: TextStyle(color: Colors.white)),
);
}).toList(),
onChanged: onCountySelected,
),
),
],
),
);
},
districtBuilder:
(
BuildContext context,
List<TaiwanCityModel> districts,
TaiwanCityModel? selectedDistrict,
void Function(TaiwanCityModel?)? onDistrictSelected,
String hintText,
bool enabled,
) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: enabled ? [Colors.green, Colors.lightGreen] : [Colors.grey.shade500, Colors.grey.shade500],
),
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Padding(
padding: EdgeInsets.all(12),
child: Icon(Icons.location_on, color: enabled ? Colors.white : Colors.grey.shade100),
),
Expanded(
child: DropdownButton<TaiwanCityModel>(
iconDisabledColor: Colors.grey.shade100,
value: selectedDistrict,
hint: Text(hintText, style: TextStyle(color: enabled ? Colors.white : Colors.grey.shade100)),
isExpanded: true,
underline: SizedBox.shrink(),
dropdownColor: Colors.green,
items: enabled
? districts
.map(
(district) => DropdownMenuItem<TaiwanCityModel>(
value: district,
child: Text('${district.townName} (${district.zipCode})', style: TextStyle(color: Colors.white)),
),
)
.toList()
: null,
onChanged: enabled ? onDistrictSelected : null,
),
),
],
),
);
},
layoutBuilder: (BuildContext context, Widget countyWidget, Widget districtWidget) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, spacing: 12, children: [countyWidget, districtWidget]),
),
);
},
)
Custom Builder 2 (自訂樣式 2) #

TaiwanCityPicker(
defaultCountyCode: '63000',
countyBuilder:
(
BuildContext context,
List<TaiwanCityModel> counties,
TaiwanCityModel? selectedCounty,
void Function(TaiwanCityModel?) onCountySelected,
String hintText,
) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SegmentedButton<TaiwanCityModel>(
segments: counties.map((county) {
return ButtonSegment<TaiwanCityModel>(
value: county,
label: Text(county.countyName, style: TextStyle(fontSize: 12)),
);
}).toList(),
emptySelectionAllowed: true,
selected: selectedCounty != null ? {selectedCounty} : {},
onSelectionChanged: (Set<TaiwanCityModel> selection) {
onCountySelected(selection.isNotEmpty ? selection.first : null);
},
multiSelectionEnabled: false,
showSelectedIcon: false,
),
);
},
districtBuilder:
(
BuildContext context,
List<TaiwanCityModel> districts,
TaiwanCityModel? selectedDistrict,
void Function(TaiwanCityModel?)? onDistrictSelected,
String hintText,
bool enabled,
) {
return Expanded(
child: ListView(
children: districts.map((district) {
return RadioListTile<TaiwanCityModel>(
title: Text('(${district.zipCode}) ${district.townName}'),
value: district,
contentPadding: EdgeInsets.zero,
groupValue: selectedDistrict,
onChanged: enabled ? onDistrictSelected : null,
);
}).toList(),
),
);
},
layoutBuilder: (BuildContext context, Widget countyWidget, Widget districtWidget) {
return SizedBox(
height: 500,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [SizedBox(height: 8), countyWidget, SizedBox(height: 8), districtWidget],
),
);
},
onChange: (ChangeType changeType, SelectedCounty? county, SelectedDistrict? district) {},
)