Android 地址選擇器,實現省市區三級聯動
阿新 • • 發佈:2019-01-04
最近專案裡面用到了一個地址選擇器,實現現在主流的WheelView滑動選擇,整理了下,做了個Demo.廢話不多說,直接上程式碼:
主佈局:
MainActivity:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.user.myapplication.MainActivity"> <TextView android:id="@+id/select_address_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="15sp" android:text="選擇地址" /> </RelativeLayout>
主要的類:package com.example.user.myapplication; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private TextView select_address_tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); select_address_tv= (TextView) findViewById(R.id.select_address_tv); select_address_tv .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ChangeAddressPopwindow mChangeAddressPopwindow = new ChangeAddressPopwindow(MainActivity.this); mChangeAddressPopwindow.setAddress("廣東", "深圳", "福田區"); mChangeAddressPopwindow.showAtLocation(select_address_tv, Gravity.BOTTOM, 0, 0); mChangeAddressPopwindow .setAddresskListener(new ChangeAddressPopwindow.OnAddressCListener() { @Override public void onClick(String province, String city, String area) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, province + "-" + city + "-" + area, Toast.LENGTH_LONG).show(); select_address_tv.setText(province + city + area); } }); } }); } }
彈出框佈局:package com.example.user.myapplication; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.view.View; import android.view.ViewGroup; import android.widget.PopupWindow; import android.widget.TextView; import com.example.user.myapplication.wheelview.OnWheelChangedListener; import com.example.user.myapplication.wheelview.OnWheelScrollListener; import com.example.user.myapplication.wheelview.WheelView; import com.example.user.myapplication.wheelview.adapter.AbstractWheelTextAdapter1; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class ChangeAddressPopwindow extends PopupWindow implements View.OnClickListener { private WheelView wvProvince; private WheelView wvCitys; private WheelView wvArea; private View lyChangeAddress; private View lyChangeAddressChild; private TextView btnSure; private TextView btnCancel; private Context context; private JSONObject mJsonObj; /** * 所有省 */ private String[] mProvinceDatas; /** * key - 省 value - 市s */ private Map<String, String[]> mCitisDatasMap = new HashMap<String, String[]>(); /** * key - 市 values - 區s */ private Map<String, String[]> mAreaDatasMap = new HashMap<String, String[]>(); private ArrayList<String> arrProvinces = new ArrayList<String>(); private ArrayList<String> arrCitys = new ArrayList<String>(); private ArrayList<String> arrAreas = new ArrayList<String>(); private AddressTextAdapter provinceAdapter; private AddressTextAdapter cityAdapter; private AddressTextAdapter areaAdapter; private String strProvince = "廣東"; private String strCity = "深圳"; private String strArea = "福田區"; private OnAddressCListener onAddressCListener; private int maxsize = 14; private int minsize = 12; public ChangeAddressPopwindow(final Context context) { super(context); this.context = context; View view=View.inflate(context,R.layout.edit_changeaddress_pop_layout,null); wvProvince = (WheelView) view.findViewById(R.id.wv_address_province); wvCitys = (WheelView) view.findViewById(R.id.wv_address_city); wvArea = (WheelView)view. findViewById(R.id.wv_address_area); lyChangeAddress = view.findViewById(R.id.ly_myinfo_changeaddress); lyChangeAddressChild = view.findViewById(R.id.ly_myinfo_changeaddress_child); btnSure = (TextView) view.findViewById(R.id.btn_myinfo_sure); btnCancel = (TextView)view. findViewById(R.id.btn_myinfo_cancel); //設定SelectPicPopupWindow的View this.setContentView(view); //設定SelectPicPopupWindow彈出窗體的寬 this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); //設定SelectPicPopupWindow彈出窗體的高 this.setHeight(ViewGroup.LayoutParams.MATCH_PARENT); //設定SelectPicPopupWindow彈出窗體可點選 this.setFocusable(true); //設定SelectPicPopupWindow彈出窗體動畫效果 // this.setAnimationStyle(R.style.AnimBottom); //例項化一個ColorDrawable顏色為半透明 ColorDrawable dw = new ColorDrawable(0xb0000000); //設定SelectPicPopupWindow彈出窗體的背景 this.setBackgroundDrawable(dw); lyChangeAddressChild.setOnClickListener(this); btnSure.setOnClickListener(this); btnCancel.setOnClickListener(this); initJsonData(); initDatas(); initProvinces(); provinceAdapter = new AddressTextAdapter(context, arrProvinces, getProvinceItem(strProvince), maxsize, minsize); wvProvince.setVisibleItems(5); wvProvince.setViewAdapter(provinceAdapter); wvProvince.setCurrentItem(getProvinceItem(strProvince)); initCitys(mCitisDatasMap.get(strProvince)); cityAdapter = new AddressTextAdapter(context, arrCitys, getCityItem(strCity), maxsize, minsize); wvCitys.setVisibleItems(5); wvCitys.setViewAdapter(cityAdapter); wvCitys.setCurrentItem(getCityItem(strCity)); initAreas(mAreaDatasMap.get(strCity)); areaAdapter = new AddressTextAdapter(context, arrAreas, getAreaItem(strArea), maxsize, minsize); wvArea.setVisibleItems(5); wvArea.setViewAdapter(areaAdapter); wvArea.setCurrentItem(getAreaItem(strArea)); wvProvince.addChangingListener(new OnWheelChangedListener() { @Override public void onChanged(WheelView wheel, int oldValue, int newValue) { // TODO Auto-generated method stub String currentText = (String) provinceAdapter.getItemText(wheel.getCurrentItem()); strProvince = currentText; setTextviewSize(currentText, provinceAdapter); String[] citys = mCitisDatasMap.get(currentText); initCitys(citys); cityAdapter = new AddressTextAdapter(context, arrCitys, 0, maxsize, minsize); wvCitys.setVisibleItems(5); wvCitys.setViewAdapter(cityAdapter); wvCitys.setCurrentItem(0); setTextviewSize("0", cityAdapter); //根據市,地區聯動 String[] areas = mAreaDatasMap.get(citys[0]); initAreas(areas); areaAdapter = new AddressTextAdapter(context, arrAreas, 0, maxsize, minsize); wvArea.setVisibleItems(5); wvArea.setViewAdapter(areaAdapter); wvArea.setCurrentItem(0); setTextviewSize("0", areaAdapter); } }); wvProvince.addScrollingListener(new OnWheelScrollListener() { @Override public void onScrollingStarted(WheelView wheel) { // TODO Auto-generated method stub } @Override public void onScrollingFinished(WheelView wheel) { // TODO Auto-generated method stub String currentText = (String) provinceAdapter.getItemText(wheel.getCurrentItem()); setTextviewSize(currentText, provinceAdapter); } }); wvCitys.addChangingListener(new OnWheelChangedListener() { @Override public void onChanged(WheelView wheel, int oldValue, int newValue) { // TODO Auto-generated method stub String currentText = (String) cityAdapter.getItemText(wheel.getCurrentItem()); strCity = currentText; setTextviewSize(currentText, cityAdapter); //根據市,地區聯動 String[] areas = mAreaDatasMap.get(currentText); initAreas(areas); areaAdapter = new AddressTextAdapter(context, arrAreas, 0, maxsize, minsize); wvArea.setVisibleItems(5); wvArea.setViewAdapter(areaAdapter); wvArea.setCurrentItem(0); setTextviewSize("0", areaAdapter); } }); wvCitys.addScrollingListener(new OnWheelScrollListener() { @Override public void onScrollingStarted(WheelView wheel) { // TODO Auto-generated method stub } @Override public void onScrollingFinished(WheelView wheel) { // TODO Auto-generated method stub String currentText = (String) cityAdapter.getItemText(wheel.getCurrentItem()); setTextviewSize(currentText, cityAdapter); } }); wvArea.addChangingListener(new OnWheelChangedListener() { @Override public void onChanged(WheelView wheel, int oldValue, int newValue) { // TODO Auto-generated method stub String currentText = (String) areaAdapter.getItemText(wheel.getCurrentItem()); strArea = currentText; setTextviewSize(currentText, cityAdapter); } }); wvArea.addScrollingListener(new OnWheelScrollListener() { @Override public void onScrollingStarted(WheelView wheel) { // TODO Auto-generated method stub } @Override public void onScrollingFinished(WheelView wheel) { // TODO Auto-generated method stub String currentText = (String) areaAdapter.getItemText(wheel.getCurrentItem()); setTextviewSize(currentText, areaAdapter); } }); } private class AddressTextAdapter extends AbstractWheelTextAdapter1 { ArrayList<String> list; protected AddressTextAdapter(Context context, ArrayList<String> list, int currentItem, int maxsize, int minsize) { super(context, R.layout.item_birth_year, NO_RESOURCE, currentItem, maxsize, minsize); this.list = list; setItemTextResource(R.id.tempValue); } @Override public View getItem(int index, View cachedView, ViewGroup parent) { View view = super.getItem(index, cachedView, parent); return view; } @Override public int getItemsCount() { return list.size(); } @Override protected CharSequence getItemText(int index) { return list.get(index) + ""; } } /** * 設定字型大小 * * @param curriteItemText * @param adapter */ public void setTextviewSize(String curriteItemText, AddressTextAdapter adapter) { ArrayList<View> arrayList = adapter.getTestViews(); int size = arrayList.size(); String currentText; for (int i = 0; i < size; i++) { TextView textvew = (TextView) arrayList.get(i); currentText = textvew.getText().toString(); if (curriteItemText.equals(currentText)) { textvew.setTextSize(14); } else { textvew.setTextSize(12); } } } public void setAddresskListener(OnAddressCListener onAddressCListener) { this.onAddressCListener = onAddressCListener; } @Override public void onClick(View v) { // TODO Auto-generated method stub if (v == btnSure) { if (onAddressCListener != null) { onAddressCListener.onClick(strProvince, strCity,strArea); } } else if (v == btnCancel) { } else if (v == lyChangeAddressChild) { return; } else { // dismiss(); } dismiss(); } /** * 回撥介面 * * @author Administrator * */ public interface OnAddressCListener { public void onClick(String province, String city, String area); } /** * 從檔案中讀取地址資料 */ private void initJsonData() { try { StringBuffer sb = new StringBuffer(); InputStream is = context.getClass().getClassLoader().getResourceAsStream("assets/" + "city.json"); int len = -1; byte[] buf = new byte[1024]; while ((len = is.read(buf)) != -1) { sb.append(new String(buf, 0, len, "gbk")); } is.close(); mJsonObj = new JSONObject(sb.toString()); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } /** * 解析整個Json物件,完成後釋放Json物件的記憶體 */ private void initDatas() { try { JSONArray jsonArray = mJsonObj.getJSONArray("citylist"); mProvinceDatas = new String[jsonArray.length()]; for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonP = jsonArray.getJSONObject(i);// 每個省的json物件 String province = jsonP.getString("p");// 省名字 mProvinceDatas[i] = province; JSONArray jsonCs = null; try { /** * Throws JSONException if the mapping doesn't exist or is * not a JSONArray. */ jsonCs = jsonP.getJSONArray("c"); } catch (Exception e1) { continue; } String[] mCitiesDatas = new String[jsonCs.length()]; for (int j = 0; j < jsonCs.length(); j++) { JSONObject jsonCity = jsonCs.getJSONObject(j); String city = jsonCity.getString("n");// 市名字 mCitiesDatas[j] = city; JSONArray jsonAreas = null; try { /** * Throws JSONException if the mapping doesn't exist or * is not a JSONArray. */ jsonAreas = jsonCity.getJSONArray("a"); } catch (Exception e) { continue; } String[] mAreasDatas = new String[jsonAreas.length()];// 當前市的所有區 for (int k = 0; k < jsonAreas.length(); k++) { String area = jsonAreas.getJSONObject(k).getString("s");// 區域的名稱 mAreasDatas[k] = area; } mAreaDatasMap.put(city, mAreasDatas); } mCitisDatasMap.put(province, mCitiesDatas); } } catch (JSONException e) { e.printStackTrace(); } mJsonObj = null; } /** * 初始化省會 */ public void initProvinces() { int length = mProvinceDatas.length; for (int i = 0; i < length; i++) { arrProvinces.add(mProvinceDatas[i]); } } /** * 根據省會,生成該省會的所有城市 * * @param citys */ public void initCitys(String[] citys) { if (citys != null) { arrCitys.clear(); int length = citys.length; for (int i = 0; i < length; i++) { arrCitys.add(citys[i]); } } else { String[] city = mCitisDatasMap.get("廣東"); arrCitys.clear(); int length = city.length; for (int i = 0; i < length; i++) { arrCitys.add(city[i]); } } if (arrCitys != null && arrCitys.size() > 0 && !arrCitys.contains(strCity)) { strCity = arrCitys.get(0); } } /** * 根據城市,生成該城市的所有地區 * * @param areas */ public void initAreas(String[] areas) { if (areas != null) { arrAreas.clear(); int length = areas.length; for (int i = 0; i < length; i++) { arrAreas.add(areas[i]); } } else { String[] area = mAreaDatasMap.get("深圳"); arrAreas.clear(); int length = area.length; for (int i = 0; i < length; i++) { arrAreas.add(area[i]); } } if (arrAreas != null && arrAreas.size() > 0 && !arrAreas.contains(strArea)) { strArea = arrAreas.get(0); } } /** * 初始化地點 * * @param province * @param city */ public void setAddress(String province, String city, String area) { if (province != null && province.length() > 0) { this.strProvince = province; } if (city != null && city.length() > 0) { this.strCity = city; } if (area != null && area.length() > 0) { this.strArea = area; } } /** * 返回省會索引,沒有就返回預設“廣東” * * @param province * @return */ public int getProvinceItem(String province) { int size = arrProvinces.size(); int provinceIndex = 0; boolean noprovince = true; for (int i = 0; i < size; i++) { if (province.equals(arrProvinces.get(i))) { noprovince = false; return provinceIndex; } else { provinceIndex++; } } if (noprovince) { strProvince = "廣東"; return 18; } return provinceIndex; } /** * 得到城市索引,沒有返回預設“深圳” * * @param city * @return */ public int getCityItem(String city) { int size = arrCitys.size(); int cityIndex = 0; boolean nocity = true; for (int i = 0; i < size; i++) { System.out.println(arrCitys.get(i)); if (city.equals(arrCitys.get(i))) { nocity = false; return cityIndex; } else { cityIndex++; } } if (nocity) { strCity = "深圳"; return 2; } return cityIndex; } /** * 得到地區索引,沒有返回預設“福田區” * * @param area * @return */ public int getAreaItem(String area) { int size = arrAreas.size(); int areaIndex = 0; boolean noarea = true; for (int i = 0; i < size; i++) { System.out.println(arrAreas.get(i)); if (area.equals(arrAreas.get(i))) { noarea = false; return areaIndex; } else { areaIndex++; } } if (noarea) { strArea = "福田區"; return 1; } return areaIndex; } }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ly_myinfo_changeaddress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:gravity="bottom"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/ly_myinfo_changeaddress_child"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#ffffff"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="44dp"
>
<TextView
android:id="@+id/btn_myinfo_cancel"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="12dp"
android:text="取消"
android:gravity="center"
android:layout_alignParentLeft="true"
android:layout_marginRight="15dip"
android:textColor="#e84515"
android:textSize="13sp" />
<TextView
android:id="@+id/btn_myinfo_sure"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
android:text="完成"
android:textColor="#e84515"
android:paddingRight="12dp"
android:textSize="12sp" />
</RelativeLayout>
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#d8d8d8"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="160dip"
android:orientation="horizontal"
android:gravity="center_vertical">
<com.example.user.myapplication.wheelview.WheelView
android:id="@+id/wv_address_province"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
/>
<com.example.user.myapplication.wheelview.WheelView
android:id="@+id/wv_address_city"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
/>
<com.example.user.myapplication.wheelview.WheelView
android:id="@+id/wv_address_area"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
執行效果圖: