Android——實現全國省市區地區選擇
阿新 • • 發佈:2019-01-11
android的地區選擇,這個實在是太常見了,比如淘寶下單後的填寫地址裡面也有地區選擇功能,微信裡面也有收貨地址,再者一些app的定位選擇等等,
實現起來也並不是很困難的事,網上也有全國省市區的介面api,調介面的方式更簡單,只不過網路請求速度慢了些,寫了個demo,在本地的省市區json檔案集合實現全國三級地區選擇,這裡我也主要貼下主要的程式碼,後面把專案的下載地址分享出來。
專案結構:
主要程式碼,ShowRegionActivity類:
package com.lai.regionselection;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* Created by laiyingtang on 2016/8/3.
*/
public class ShowRegionActivity extends Activity {
private Spinner spinner_sheng;//省
private Spinner spinner_shi;//市
private Spinner spinner_qu;//區
private EditText et_detailAddress;//輸入詳細地址
private Button btn_confirm;//確認按鈕
private int resultCode = 102;//返回碼
//全域性的jsonObject
private JSONObject jsonObject;//把全國的省市區的資訊以json的格式儲存,解析完成後賦值為null
private String[] allProv;//所有的省
private ArrayAdapter<String> provinceAdapter;//省份資料介面卡
private ArrayAdapter<String> cityAdapter;//城市資料介面卡
private ArrayAdapter<String> areaAdapter;//區縣資料介面卡
private String[] allSpinList;//在spinner中選出來的地址,後面需要用空格隔開省市區
private String address;//用來接收intent的引數
private String allAddress;//用來接收intent引數
private String provinceName;//省的名字
private String areaName;//區的名字
private Boolean isFirstLoad = true;//判斷是不是最近進入對話方塊
private Boolean ifSetFirstAddress = true;//判斷是否已經設定了,初始的詳細地址
//省市區的集合
private Map<String, String[]> cityMap = new HashMap<String, String[]>();//key:省p---value:市n value是一個集合
private Map<String, String[]> areaMap = new HashMap<String, String[]>();//key:市n---value:區s 區也是一個集合
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//設定視窗不顯示標題
setContentView(R.layout.activity_region);
initJsonData();//初始化json資料
initDatas();//初始化省市區資料
initView();//初始化控制元件
initClick();//初始化點選
setSpinnerData();//為spinner設定值
}
/**
* spinner設定值(預設設定值)
*/
private void setSpinnerData() {
int selectPosition = 0;//有資料傳入時
address = getIntent().getStringExtra("address");
allAddress = getIntent().getStringExtra("allAddress");
if (address != null && !address.equals("") && allAddress != null && !allAddress.equals("")) {
allSpinList = address.split(" ");//用空格隔開allSpinList地址
}
/**
* 設定省市區的介面卡,進行動態設定
*/
provinceAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);//系統預設的
for (int i = 0; i < allProv.length; i++) {
//給spinner省賦值,設定預設值
if (address != null && !address.equals("") && allAddress != null && !allAddress.equals("")&& allSpinList.length > 0 && allSpinList[0].equals(allProv[i])) {
selectPosition = i;
}
provinceAdapter.add(allProv[i]);//新增每一個省
}
provinceAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);//按下的效果
spinner_sheng.setAdapter(provinceAdapter);
spinner_sheng.setSelection(selectPosition);//設定選中的省,預設
//市
cityAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
cityAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_shi.setAdapter(cityAdapter);
//區縣
areaAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
areaAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner_qu.setAdapter(areaAdapter);
setListener();//設定spinner的點選監聽
}
//設定spinner的點選監聽
private void setListener() {
//省
spinner_sheng.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
provinceName = parent.getSelectedItem() + "";//獲取點選列表spinner item的省名字
if (isFirstLoad) {
// 判斷是否省市區都存在
if (address != null && !address.equals("") && allAddress != null && !allAddress.equals("")&& allSpinList.length > 1 && allSpinList.length < 3) {
updateCityAndArea(provinceName, allSpinList[1], null);//更新市和區
} else if (address != null && !address.equals("") && allAddress != null && !allAddress.equals("") && allSpinList.length >= 3) {
//存在省市區
//去更新
updateCityAndArea(provinceName, allSpinList[1], allSpinList[2]);
} else {
updateCityAndArea(provinceName, null, null);
}
} else {
updateCityAndArea(provinceName, null, null);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//市
spinner_shi.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (!isFirstLoad) {
//更新區
updateArea(parent.getSelectedItem() + "", null);
} else {
if (address != null && !address.equals("") && allAddress != null && !allAddress.equals("") && allSpinList.length == 4) {
et_detailAddress.setText(allSpinList[3]);//沒有進入區的對話方塊,
}
}
isFirstLoad = false;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//區
spinner_qu.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//直接獲取區的名字
areaName = parent.getSelectedItem() + "";
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/**
* 根據當前的省,更新市和區的資訊
*/
private void updateCityAndArea(Object object, Object city, Object area) {
int selectPosition = 0;//有資料時,進行匹配城市,預設選中
String[] cities = cityMap.get(object);
cityAdapter.clear();//清空adapter的資料
for (int i = 0; i < cities.length; i++) {
if (city != null && city.toString().equals(cities[i])) {//判斷傳入的市在集合中匹配
selectPosition = i;
}
cityAdapter.add(cities[i]);//將這個列表“市”新增到adapter中
}
cityAdapter.notifyDataSetChanged();//重新整理
if (city == null) {
updateArea(cities[0], null);//更新區,沒有市則預設第一個給它
} else {
spinner_shi.setSelection(selectPosition);
updateArea(city, area);//穿入的區去集合中匹配
}
}
//根據當前的市,更新區的資訊
private void updateArea(Object object, Object myArea) {
boolean isArea = false;//判斷第三個地址是地區還是詳細地址
int selectPosition = 0;//當有資料時,進行匹配地區,預設選中
String[] area = areaMap.get(object);
areaAdapter.clear();//清空
if (area != null) {
for (int i = 0; i < area.length; i++) {
if (myArea != null && myArea.toString().equals(area[i])) {//去集合中匹配
selectPosition = i;
isArea = true;//地區
}
areaAdapter.add(area[i]);//填入到這個列表
}
areaAdapter.notifyDataSetChanged();//重新整理
spinner_qu.setSelection(selectPosition);//預設選中
}
//第三個地址是詳細地址,並且是第一次設定edtext值,正好,地址的長度為3的時候,設定詳細地址
if (!isArea && ifSetFirstAddress && address != null && !address.equals("") && allAddress != null && !allAddress.equals("") && allSpinList.length == 3) {
et_detailAddress.setText(allSpinList[2]);
ifSetFirstAddress = false;
}
}
//初始化省市區資料
private void initDatas() {
try {
JSONArray jsonArray = jsonObject.getJSONArray("citylist");//獲取整個json資料
allProv = new String[jsonArray.length()];//封裝資料
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonP = jsonArray.getJSONObject(i);//jsonArray轉jsonObject
String provStr = jsonP.getString("p");//獲取所有的省
allProv[i] = provStr;//封裝所有的省
JSONArray jsonCity = null;
try {
jsonCity = jsonP.getJSONArray("c");//在所有的省中取出所有的市,轉jsonArray
} catch (Exception e) {
continue;
}
//所有的市
String[] allCity = new String[jsonCity.length()];//所有市的長度
for (int c = 0; c < jsonCity.length(); c++) {
JSONObject jsonCy = jsonCity.getJSONObject(c);//轉jsonObject
String cityStr = jsonCy.getString("n");//取出所有的市
allCity[c] = cityStr;//封裝市集合
JSONArray jsonArea = null;
try {
jsonArea = jsonCy.getJSONArray("a");//在從所有的市裡面取出所有的區,轉jsonArray
} catch (Exception e) {
continue;
}
String[] allArea = new String[jsonArea.length()];//所有的區
for (int a = 0; a < jsonArea.length(); a++) {
JSONObject jsonAa = jsonArea.getJSONObject(a);
String areaStr = jsonAa.getString("s");//獲取所有的區
allArea[a] = areaStr;//封裝起來
}
areaMap.put(cityStr, allArea);//某個市取出所有的區集合
}
cityMap.put(provStr, allCity);//某個省取出所有的市,
}
} catch (JSONException e) {
e.printStackTrace();
}
jsonObject = null;//清空所有的資料
}
/**
* 從assert資料夾中獲取json資料
*/
private void initJsonData() {
try {
StringBuffer sb = new StringBuffer();
InputStream is = getAssets().open("city.json");//開啟json資料
byte[] by = new byte[is.available()];//轉位元組
int len = -1;
while ((len = is.read(by)) != -1) {
sb.append(new String(by, 0, len, "gb2312"));//根據位元組長度設定編碼
}
is.close();//關閉流
jsonObject = new JSONObject(sb.toString());//為json賦值
} catch (Exception e) {
e.printStackTrace();
}
}
//初始化點選
private void initClick() {
btn_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//把值返回給MainActivity
Intent intent = new Intent();
areaName = spinner_qu.getSelectedItem() == null ? "" : spinner_qu.getSelectedItem().toString();
intent.putExtra("address", spinner_sheng.getSelectedItem() + " " + spinner_shi.getSelectedItem() + " " + areaName);
intent.putExtra("allAddress", et_detailAddress.getText().toString());
setResult(resultCode, intent);
finish();
}
});
}
//初始化控制元件
private void initView() {
spinner_sheng = (Spinner) findViewById(R.id.spinner_sheng);
spinner_shi = (Spinner) findViewById(R.id.spinner_shi);
spinner_qu = (Spinner) findViewById(R.id.spinner_qu);
et_detailAddress = (EditText) findViewById(R.id.et_detailAddress);
btn_confirm = (Button) findViewById(R.id.btn_confirm);
}
}
效果如下:
註釋也寫了,大家慢慢消化吧!邏輯很清晰,只是程式碼量多了些。如果用Rxjava或許容易懂些,最後我把專案地址附上