讀取本地json資料實現省市區三級聯動PickerView
阿新 • • 發佈:2019-01-07
這個功能在應用中還是用的比較多的,這裡我將之前的一個電商專案中使用到的省市區三級聯動選擇器的程式碼粘出來,需要的自取。實現UI如圖:
首先是省市區的json資料
專案目錄結構
使用程式碼
- 匯入jar包
compile 'com.bigkoo:pickerview:2.1.0'
- 在Activity的onCreat()方法中初始化
OptionsPickerView pvOptions = new OptionsPickerView(this);
- 獲取json資料
private ArrayList<ProvinceBean> options1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();
private void hasJsonData() {
Gson gson = new Gson();
try {
InputStream in = getResources().getAssets().open("area.json");
int available = in.available();
byte[] b = new byte[available];
in.read(b);
String json = new String(b, "UTF-8");
//地址類
area = gson.fromJson(json, Area.class);
ArrayList<Area.RootBean> citylist = area.getRoot();
for (Area.RootBean province : citylist
) {
String provinceName = province.getProvince();
ArrayList<Area.RootBean.CitiesBean> c = province.getCities();
options1Items.add(new ProvinceBean(0, provinceName, "", ""));
ArrayList<ArrayList<String>> options3Items_01 = new ArrayList<ArrayList<String>>();
ArrayList<String> options2Items_01 = new ArrayList<String>();
if (c != null) {
for (Area.RootBean.CitiesBean area : c
) {
options2Items_01.add(area.getCity());
ArrayList<Area.RootBean.CitiesBean.CountiesBean> a = area.getCounties();
ArrayList<String> options3Items_01_01 = new ArrayList<String>();
if (a != null) {
for (Area.RootBean.CitiesBean.CountiesBean street : a
) {
options3Items_01_01.add(street.getCounty());
}
options3Items_01.add(options3Items_01_01);
} else {
options3Items_01_01.add("");
options3Items_01.add(options3Items_01_01);
}
}
options2Items.add(options2Items_01);
} else {
options2Items_01.add("");
}
options3Items.add(options3Items_01);
ArrayList<String> options3Items_01_01 = new ArrayList<String>();
options3Items_01_01.add("");
options3Items_01.add(options3Items_01_01);
}
} catch (IOException e) {
e.printStackTrace();
}
}
- 將json資料賦值給PickerView
private void initPickerView(BDLocation mlocation) {
pvOptions.setPicker(options1Items, options2Items, options3Items, true);
pvOptions.setTitle("選擇城市");
pvOptions.setCyclic(false, false, false);
int p1 = 0;
int p2 = 0;
int p3 = 0;
if (mlocation != null) {
for (int i1 = 0; i1 < options1Items.size(); i1++) {
if (options1Items.get(i1).getName().equals(mlocation.getProvince())) {
p1 = i1;
}
for (int i2 = 0; i2 < options2Items.get(i1).size(); i2++) {
if (options2Items.get(i1).get(i2).equals(mlocation.getCity())) {
p2 = i2;
}
for (int i3 = 0; i3 < options3Items.get(i1).get(i2).size(); i3++) {
if (options3Items.get(i1).get(i2).get(i3).equals(mlocation.getDistrict())) {
p3 = i3;
}
}
}
}
}
pvOptions.setSelectOptions(p1, p2, p3); //--選中當前位置
pvOptions.setCancelable(true);
pvOptions.setOnoptionsSelectListener(new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3) {
String p1 = options1Items.get(options1).getPickerViewText();
String address;
if ("北京市".equals(p1) || "上海市".equals(p1) || "天津市".equals(p1) || "重慶市".equals(p1)) {
//--------------baidu地理編碼定位------------------------
cityLocation = options1Items.get(options1).getPickerViewText();
addressLocation = options3Items.get(options1).get(option2).get(options3);
//------------------------------------------------------
address = options1Items.get(options1).getPickerViewText()
+ " " + options3Items.get(options1).get(option2).get(options3);
provinceCode = area.getRoot().get(options1).getProvinceCode();
cityCode = area.getRoot().get(options1).getCities().get(option2).getCityCode();
countyCode = area.getRoot().get(options1).getCities().get(option2).getCounties().get(options3).getCountyCode();
} else if ("澳門".contains(p1) || "香港".contains(p1) || "臺灣省".equals(p1)) {
//--------------baidu地理編碼定位------------------------
cityLocation = options1Items.get(options1).getPickerViewText();
addressLocation = options2Items.get(options1).get(option2);
//------------------------------------------------------
address = options1Items.get(options1).getPickerViewText()
+ " " + options2Items.get(options1).get(option2);
provinceCode = area.getRoot().get(options1).getProvinceCode();
cityCode = area.getRoot().get(options1).getCities().get(option2).getCityCode();
} else {
//--------------baidu地理編碼定位------------------------
// cityLocation = options1Items.get(options1).getPickerViewText()+options2Items.get(options1).get(option2);
cityLocation = options2Items.get(options1).get(option2);
addressLocation = options3Items.get(options1).get(option2).get(options3);
//------------------------------------------------------
address = options1Items.get(options1).getPickerViewText()
+ " " + options2Items.get(options1).get(option2)
+ " " + options3Items.get(options1).get(option2).get(options3);
provinceCode = area.getRoot().get(options1).getProvinceCode();
cityCode = area.getRoot().get(options1).getCities().get(option2).getCityCode();
countyCode = area.getRoot().get(options1).getCities().get(option2).getCounties().get(options3).getCountyCode();
}
hintInfo.setVisibility(View.INVISIBLE);
showAddress.setVisibility(View.VISIBLE);
showAddress.setText(address);
}
});
}
- 實體物件,滿足伸手黨《哈哈》
1、Area實體類
public class Area implements Parcelable {
private ArrayList<RootBean> root;
protected Area(Parcel in) {
}
public static final Creator<Area> CREATOR = new Creator<Area>() {
@Override
public Area createFromParcel(Parcel in) {
return new Area(in);
}
@Override
public Area[] newArray(int size) {
return new Area[size];
}
};
public ArrayList<RootBean> getRoot() {
return root;
}
public void setRoot(ArrayList<RootBean> root) {
this.root = root;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
public static class RootBean {
private int provinceCode;
private String province;
private ArrayList<CitiesBean> cities;
public int getProvinceCode() {
return provinceCode;
}
public void setProvinceCode(int provinceCode) {
this.provinceCode = provinceCode;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public ArrayList<CitiesBean> getCities() {
return cities;
}
public void setCities(ArrayList<CitiesBean> cities) {
this.cities = cities;
}
/**
*使用這個方法可以獲取文字,並判斷文字是否超長,比如“新疆維吾爾自治區”,這肯定顯示不完,我們就可以擷取後再顯示
*/
public String getPickerViewText() {
return province;
}
public static class CitiesBean {
private int cityCode;
private String city;
private int superCode;
private ArrayList<CountiesBean> counties;
public int getCityCode() {
return cityCode;
}
public void setCityCode(int cityCode) {
this.cityCode = cityCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getSuperCode() {
return superCode;
}
public void setSuperCode(int superCode) {
this.superCode = superCode;
}
public ArrayList<CountiesBean> getCounties() {
return counties;
}
public void setCounties(ArrayList<CountiesBean> counties) {
this.counties = counties;
}
public static class CountiesBean {
private int countyCode;
private String county;
private int superCode;
public int getCountyCode() {
return countyCode;
}
public void setCountyCode(int countyCode) {
this.countyCode = countyCode;
}
public String getCounty() {
return county;
}
public void setCounty(String county) {
this.county = county;
}
public int getSuperCode() {
return superCode;
}
public void setSuperCode(int superCode) {
this.superCode = superCode;
}
}
}
}
}
2、ProvinceBean
public class ProvinceBean implements IPickerViewData {
private long id;
private String name;
private String description;
private String others;
public ProvinceBean(long id,String name,String description,String others){
this.id = id;
this.name = name;
this.description = description;
this.others = others;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getOthers() {
return others;
}
public void setOthers(String others) {
this.others = others;
}
//這個用來顯示在PickerView上面的字串,PickerView會通過反射獲取getPickerViewText方法顯示出來。
public String getPickerViewText() {
//這裡還可以判斷文字超長截斷再提供顯示
if (name.length()>4){
return name.substring(0, 2);//欄位太長擷取
}
return name;
}
}
附上專案中使用到的完整類
public class AddAddressActivity extends BaseActivity {
@Bind(R.id.iv_title_left)
ImageView ivTitleLeft;
@Bind(R.id.tv_title)
TextView tvTitle;
@Bind(R.id.iv_title_right)
ImageView ivTitleRight;
@Bind(R.id.tv_score2award)
TextView tvScore2award;
@Bind(R.id.province_address)
TextView provinceAddress;
@Bind(R.id.city_address)
TextView cityAddress;
@Bind(R.id.county_address)
TextView countyAddress;
@Bind(R.id.add_address_third_iv)
ImageView addAddressThirdIv;
@Bind(R.id.floor_door_num)
EditText floorDoorNum;
@Bind(R.id.has_detail_for_map)
ImageView hasDetailForMap;
@Bind(R.id.user_name_et)
EditText userNameEt;
@Bind(R.id.detail_address)
EditText detailAddress;
@Bind(R.id.user_tel_et)
EditText userTelEt;
@Bind(R.id.set_default_address)
CheckBox setDefaultAddress;
@Bind(R.id.address_isok_btn)
Button addressIsok;
@Bind(R.id.hint_info)
LinearLayout hintInfo;
@Bind(R.id.show_address)
TextView showAddress;
OptionsPickerView pvOptions;
private ArrayList<ProvinceBean> options1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();
private Area area;
private int provinceCode;
private int cityCode;
private int countyCode;
private String addressType;
private int addressId;
private String latitude;
private String longitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_address);
ButterKnife.bind(this);
pvOptions = new OptionsPickerView(this);
//--檢測是否有定位許可權
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//去請求許可權
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 111);
} else {
initLocation();
}
hasJsonData();
initView();
}
private void initPickerView(BDLocation mlocation) {
pvOptions.setPicker(options1Items, options2Items, options3Items, true);
pvOptions.setTitle("選擇城市");
pvOptions.setCyclic(false, false, false);
int p1 = 0;
int p2 = 0;
int p3 = 0;
if (mlocation != null) {
for (int i1 = 0; i1 < options1Items.size(); i1++) {
if (options1Items.get(i1).getName().equals(mlocation.getProvince())) {
p1 = i1;
}
for (int i2 = 0; i2 < options2Items.get(i1).size(); i2++) {
if (options2Items.get(i1).get(i2).equals(mlocation.getCity())) {
p2 = i2;
}
for (int i3 = 0; i3 < options3Items.get(i1).get(i2).size(); i3++) {
if (options3Items.get(i1).get(i2).get(i3).equals(mlocation.getDistrict())) {
p3 = i3;
}
}
}
}
}
pvOptions.setSelectOptions(p1, p2, p3); //--選中當前位置
pvOptions.setCancelable(true);
pvOptions.setOnoptionsSelectListener(new OptionsPickerView.OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3) {
String p1 = options1Items.get(options1).getPickerViewText();
String address;
if ("北京市".equals(p1) || "上海市".equals(p1) || "天津市".equals(p1) || "重慶市".equals(p1)) {
//--------------baidu地理編碼定位------------------------
cityLocation = options1Items.get(options1).getPickerViewText();
addressLocation = options3Items.get(options1).get(option2).get(options3);
//------------------------------------------------------
address = options1Items.get(options1).getPickerViewText()
+ " " + options3Items.get(options1).get(option2).get(options3);
provinceCode = area.getRoot().get(options1).getProvinceCode();
cityCode = area.getRoot().get(options1).getCities().get(option2).getCityCode();
countyCode = area.getRoot().get(options1).getCities().get(option2).getCounties().get(options3).getCountyCode();
} else if ("澳門".contains(p1) || "香港".contains(p1) || "臺灣省".equals(p1)) {
//--------------baidu地理編碼定位------------------------
cityLocation = options1Items.get(options1).getPickerViewText();
addressLocation = options2Items.get(options1).get(option2);
//------------------------------------------------------
address = options1Items.get(options1).getPickerViewText()
+ " " + options2Items.get(options1).get(option2);
provinceCode = area.getRoot().get(options1).getProvinceCode();
cityCode = area.getRoot().get(options1).getCities().get(option2).getCityCode();
} else {
//--------------baidu地理編碼定位------------------------
// cityLocation = options1Items.get(options1).getPickerViewText()+options2Items.get(options1).get(option2);
cityLocation = options2Items.get(options1).get(option2);
addressLocation = options3Items.get(options1).get(option2).get(options3);
//------------------------------------------------------
address = options1Items.get(options1).getPickerViewText()
+ " " + options2Items.get(options1).get(option2)
+ " " + options3Items.get(options1).get(option2).get(options3);
provinceCode = area.getRoot().get(options1).getProvinceCode();
cityCode = area.getRoot().get(options1).getCities().get(option2).getCityCode();
countyCode = area.getRoot().get(options1).getCities().get(option2).getCounties().get(options3).getCountyCode();
}
hintInfo.setVisibility(View.INVISIBLE);
showAddress.setVisibility(View.VISIBLE);
showAddress.setText(address);
}
});
}
//---------1011zuo---------
public LocationClient mLocationClient = null;
private void initLocation() {
mLocationClient = new LocationClient(this); // 宣告LocationClient類
mLocationClient.registerLocationListener(new MyLocationListener()); // 註冊監聽函式
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);// 可選,預設高精度,設定定位模式,高精度,低功耗,僅裝置
// option.setCoorType("bd09ll");// 可選,預設gcj02,設定返回的定位結果座標系-----百度使用的座標系
option.setCoorType("gcj02");// 可選,預設gcj02,設定返回的定位結果座標系-----高德使用的就是gcj02的座標系
int span = 100;
option.setScanSpan(span);// 可選,預設0,即僅定位一次,設定發起定位請求的間隔需要大於等於1000ms才是有效的
option.setIsNeedAddress(true);// 可選,設定是否需要地址資訊,預設不需要
option.setOpenGps(true);// 可選,預設false,設定是否使用gps
option.setLocationNotify(true);// 可選,預設false,設定是否當gps有效時按照1S1次頻率輸出GPS結果
option.setIsNeedLocationDescribe(true);// 可選,預設false,設定是否需要位置語義化結果,可以在BDLocation.getLocationDescribe裡得到,結果類似於“在北京天安門附近”
mLocationClient.setLocOption(option);
mLocationClient.start();
}
/**
* 定位的回撥
*/
private class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
initPickerView(location);
}
}
//---------1011zuo---------
private void initView() {
tvScore2award.setVisibility(View.GONE);
ivTitleRight.setVisibility(View.INVISIBLE);
Intent intent = getIntent();
addressType = intent.getStringExtra("type");
if ("add".equals(addressType)) {
tvTitle.setText("新增地址");
return;
}
if ("update".equals(addressType)) {
tvTitle.setText("修改地址");
AddressListBean addressBean = intent.getParcelableExtra("addressBean");
addressId = addressBean.getAddressId();
hintInfo.setVisibility(View.INVISIBLE);
showAddress.setVisibility(View.VISIBLE);
cityLocation = addressBean.getArea().getCity();
addressLocation = addressBean.getArea().getCounty();
showAddress.setText("" + addressBean.getArea().getProvince() + addressBean.getArea().getCity() + addressBean.getArea().getCounty());
provinceCode = addressBean.getArea().getProvinceCode();
cityCode = addressBean.getArea().getCityCode();
countyCode = addressBean.getArea().getCountyCode();
detailAddress.setText(addressBean.getAddress());
floorDoorNum.setText(addressBean.getAreas()); //門牌號
userNameEt.setText(addressBean.getContactName());
userTelEt.setText(addressBean.getContactPhone());
setDefaultAddress.setChecked(addressBean.isDefault());
return;
}
}
//從地圖頁面返回的位置資訊
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (resultCode) {
case RESULT_OK:
if (data == null) {
return;
}
Bundle bundle = data.getExtras();
String address = bundle.getString("name");
DecimalFormat df = new DecimalFormat("######0.000000");
latitude = df.format(bundle.getDouble("latitude"));
longitude = df.format(bundle.getDouble("longitude"));
detailAddress.setText(address);
break;
default:
break;
}
}
@OnClick({R.id.has_detail_for_map, R.id.iv_title_left, R.id.add_address_third_iv, R.id.set_default_address, R.id.address_isok_btn})
public void onClick(View view) {
switch (view.getId()) {
case R.id.has_detail_for_map:
//--檢測是否有定位許可權
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//去請求許可權
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 112);
} else {
chooseLocationWay();
}
break;
case R.id.iv_title_left:
hintUserSave();
// toAddressManger();
break;
case R.id.add_address_third_iv:
pvOptions.show();
break;
case R.id.address_isok_btn:
addAddress();
break;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 112:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//同意
chooseLocationWay();
} else {
//拒絕
Toast.makeText(AddAddressActivity.this, "親,定位許可權被拒絕,\n請在設定中開啟", Toast.LENGTH_LONG).show();
}
break;
case 111:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//同意
initLocation();
} else {
//拒絕
Toast.makeText(AddAddressActivity.this, "親,定位許可權被拒絕,\n請在設定中開啟", Toast.LENGTH_LONG).show();
}
break;
default:
break;
}
}
//選擇定位的方式---用的V7包的
private String cityLocation = "";
private String addressLocation = "";
private void chooseLocationWay() {
String[] choose = {"定位到指定的省市區", "定位到當前位置"};
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("選擇定位方式");
builder.setItems(choose, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(AddAddressActivity.this, LocationMapActivity.class);
switch (which) {
case 0:
String text = (String) showAddress.getText();
if (TextUtils.isEmpty(text)) {
CommUtils.showSafeToast(AddAddressActivity.this, "請選擇省市區");
return;
}
//--把地址傳過去,定位
intent.putExtra("city", cityLocation);
intent.putExtra("address", addressLocation);
break;
case 1:
intent.putExtra("ctiy", "");
intent.putExtra("address", "");
break;
}
startActivityForResult(intent, 10010);
dialog.dismiss();
}
});
builder.create().show();
}
private int userId = UserInfoUtils.getUserInfoBean().getUserId();
private String address;
private String doorNum;
private String contactName;
private String contactPhone;
private boolean isDefaul;
private void addAddress() {
if (!CommUtils.isNetWorkConnected(AddAddressActivity.this)) {
ToastUtil.showShort(AddAddressActivity.this, "請檢查網路", Gravity.CENTER);
return;
}
String area = showAddress.getText().toString();
address = detailAddress.getText().toString();
doorNum = floorDoorNum.getText().toString();
contactName = userNameEt.getText().toString();
contactPhone = userTelEt.getText().toString();
isDefaul = setDefaultAddress.isChecked();
if (TextUtils.isEmpty(area)) {
CommUtils.showSafeToast(this, "請選擇省市區");
return;
}
if (TextUtils.isEmpty(doorNum)) {
CommUtils.showSafeToast(this, "門牌號為空");
return;
}
if (TextUtils.isEmpty(address)) {
CommUtils.showSafeToast(this, "詳細地址為空");
return;
}
if (TextUtils.isEmpty(contactName)) {
CommUtils.showSafeToast(this, "收貨人為空");
return;
}
if (TextUtils.isEmpty(contactPhone)) {
Comm