今天自定義了一個選擇器,可以選擇是時間還是地址,使用起來很方便,繼承popupWindow實現的,代碼很簡單,使用也簡單,效果圖如下
先看下使用方法
時間選擇器的使用
默認是顯示年月日時分秒,可以通過構造方法傳入的type值來設置要顯示的日期格式,如type爲2的話,顯示的是年月日時分,沒有秒,具體看完整代碼中的解釋,備註很清楚。
地址選擇器的使用
關於地址選擇器,如果使用xml文件引入地址信息,在這裏使用的是SAX方法對xml進行了解析,至於xml地址資源,可自行去網上尋找,很容易找到,這裏截個圖個大家看一下,主要一點要注意一下,標籤名跟格式要一致,即使網上找到的標籤名不一樣,手動修改一下就好,截圖如下:
可以看到時間選擇器跟地址選擇器在使用上的區別在於調用不同的構造方法,在這個自定義組件中,提供了三個構造方法,備註很清晰
選擇器是使用了NumberPicker來實現的,也還是比較簡單。
在activity的使用中,show()方法用於從底部彈出時間選擇器,ClickCallBack爲回調方法,用於接收左右兩邊的兩個按鈕的點擊事件,confirm回調方法中返回的還是一個json對象,方便使用。
另外代碼中還提供了兩個方法用於修改左右兩個兩個TextView的文本內容,完整代碼如下:
package com.example.testproject.widget;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class TimeSelector extends PopupWindow {
private DivNumberPicker mYearPicker;
private DivNumberPicker mMonthPicker;
private DivNumberPicker mDayPicker;
private DivNumberPicker mHourPicker;
private DivNumberPicker mMinutePicker;
private DivNumberPicker mSecondPicker;
private NumberPicker mProvincePicker;
private NumberPicker mCityPicker;
private NumberPicker mDistrictPicker;
private TextView mTvConfirm, mTvCancel;
//數據集合__混合文字
private List<String> mYearList = new ArrayList<>();
private List<String> mMonthList = new ArrayList<>();
private List<String> mDayList = new ArrayList<>();
private List<String> mHourList = new ArrayList<>();
private List<String> mMinuteList = new ArrayList<>();
private List<String> mSecondList = new ArrayList<>();
//純數字
private List<Integer> mYearNumList = new ArrayList<>();
private List<Integer> mMonthNumList = new ArrayList<>();
private List<Integer> mDayNumList = new ArrayList<>();
private List<Integer> mHourNumList = new ArrayList<>();
private List<Integer> mMinuteNumList = new ArrayList<>();
private List<Integer> mSecondNumList = new ArrayList<>();
//地址數據集合
private List<String> mProvinceList = new ArrayList<>();
private Map<String, List<String>> mCityMap = new HashMap<>();
private Map<String, List<String>> mDistrictMap = new HashMap<>();
private String[] mCityArray;
private String[] mDistrictArray;
private String[] provinceStrArray;
//當前選擇的數據
private String mCurSelProvince = "";
private String mCurSelCity = "";
private String mCurSelDistrict = "";
private Context mContext;
private ClickCallBack mClickCallBack;
private String mStrLeft = "取消";
private String mStrRight = "確認";
private int mType = 1;//1.年月日時分秒,2.年月日時分 3.年月日時,4.年月日,5.時分秒,6.時分
private String mStrType = "time";//time:表示時間選擇器,address:表示地址選擇器
private String mStrAddressPath;//地址資源
/**
* 使用此構造方法,則默認mType=1的情況下的時間選擇器
*
* @param context 上下文對象
*/
public TimeSelector(Context context) {
super(context);
mContext = context;
initView(context);
}
/**
* 使用此構造方法,mType可變的時間選擇器
*
* @param context 上下文對象
* @param mType 可變的mType
*/
public TimeSelector(Context context, int mType) {
super(context);
mContext = context;
this.mType = mType;
initView(context);
}
/**
* 使用此構造方法,則爲地址選擇器
*
* @param context 上下文對象
* @param addressPath 地址資源文件路徑,一般是assets文件夾下的xml文件
*/
public TimeSelector(Context context, String addressPath) {
super(context);
mContext = context;
mStrType = "address";
mStrAddressPath = addressPath;
initView(context);
}
private void initView(final Context context) {
//獲取屏幕寬高信息
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
if (wm != null) {
wm.getDefaultDisplay().getMetrics(dm);
}
this.setHeight(dm.heightPixels / 3);
this.setWidth(dm.widthPixels);
//動態創建外層佈局
LinearLayout llContent = new LinearLayout(context);
llContent.setOrientation(LinearLayout.VERTICAL);
llContent.setBackgroundColor(Color.WHITE);
RelativeLayout rlTitle = new RelativeLayout(context);
rlTitle.setBackgroundColor(Color.WHITE);
//動態創建兩個TextView
mTvCancel = new TextView(context);
mTvCancel.setText(mStrLeft);
mTvCancel.setTextSize(15);
mTvConfirm = new TextView(context);
mTvConfirm.setText(mStrRight);
mTvConfirm.setTextSize(15);
rlTitle.addView(mTvCancel);
rlTitle.addView(mTvConfirm);
RelativeLayout.LayoutParams rlp = (RelativeLayout.LayoutParams) mTvCancel.getLayoutParams();
rlp.setMargins(14, 12, 0, 12);
rlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
mTvCancel.setLayoutParams(rlp);
RelativeLayout.LayoutParams rlp1 = (RelativeLayout.LayoutParams) mTvConfirm.getLayoutParams();
rlp1.setMargins(0, 12, 14, 12);
rlp1.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
mTvConfirm.setLayoutParams(rlp1);
//動態創建NumberPicker
LinearLayout llDataSel = new LinearLayout(context);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
llDataSel.setOrientation(LinearLayout.HORIZONTAL);
lp.weight = 1;
lp.setMargins(7, 0, 7, 0);
if ("time".equals(mStrType)) {
mYearPicker = new DivNumberPicker(context);
mMonthPicker = new DivNumberPicker(context);
mDayPicker = new DivNumberPicker(context);
mHourPicker = new DivNumberPicker(context);
mMinutePicker = new DivNumberPicker(context);
mSecondPicker = new DivNumberPicker(context);
mYearPicker.setLayoutParams(lp);
mMonthPicker.setLayoutParams(lp);
mDayPicker.setLayoutParams(lp);
mHourPicker.setLayoutParams(lp);
mMinutePicker.setLayoutParams(lp);
mSecondPicker.setLayoutParams(lp);
llDataSel.addView(mYearPicker);
llDataSel.addView(mMonthPicker);
llDataSel.addView(mDayPicker);
llDataSel.addView(mHourPicker);
llDataSel.addView(mMinutePicker);
llDataSel.addView(mSecondPicker);
} else if ("address".equals(mStrType)) {
mProvincePicker = new DivNumberPicker(context);
mCityPicker = new DivNumberPicker(context);
mDistrictPicker = new DivNumberPicker(context);
mProvincePicker.setLayoutParams(lp);
mCityPicker.setLayoutParams(lp);
mDistrictPicker.setLayoutParams(lp);
llDataSel.addView(mProvincePicker);
llDataSel.addView(mCityPicker);
llDataSel.addView(mDistrictPicker);
}
llContent.addView(rlTitle);
llContent.addView(llDataSel);
this.setContentView(llContent);
if ("time".equals(mStrType))
initData(mType);
else if ("address".equals(mStrType))
getAddressData(context, mStrAddressPath);
initListener();
}
/**
* 添加監聽方法
*/
private void initListener() {
mTvConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mClickCallBack != null) {
if ("time".equals(mStrType))
mClickCallBack.confirm(getResult());
else if ("address".equals(mStrType))
mClickCallBack.confirm(getAddressResult());
}
setAlpha(1.0f);
}
});
mTvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mClickCallBack != null)
mClickCallBack.cancel();
setAlpha(1.0f);
}
});
this.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
setAlpha(1.0f);
}
});
if (mProvincePicker != null) {
//監聽事件
mProvincePicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
/**
* 每當選擇的值改變時都會調用一次
* @param oldVal 改變前的值
* @param newVal 改變後的值
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
//改變市,區的值
mCurSelProvince = provinceStrArray[picker.getValue()];
mCityArray = mCityMap.get(mCurSelProvince).toArray(new String[0]);
mCityPicker.setDisplayedValues(null);
mCityPicker.setMaxValue(mCityArray.length - 1); //設置最大值
mCityPicker.setDisplayedValues(mCityArray);
mCurSelCity = mCityArray[0];
mDistrictArray = mDistrictMap.get(mCurSelCity).toArray(new String[0]);
mDistrictPicker.setDisplayedValues(null);
mDistrictPicker.setMaxValue(mDistrictArray.length - 1); //設置最大值
mDistrictPicker.setDisplayedValues(mDistrictArray);
}
});
}
if (mCityPicker != null) {
mCityPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
/**
* 每當選擇的值改變時都會調用一次
* @param oldVal 改變前的值
* @param newVal 改變後的值
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
//獲取當前位置,設置地區
mCurSelCity = mCityArray[picker.getValue()];
mDistrictArray = mDistrictMap.get(mCurSelCity).toArray(new String[0]);
mDistrictPicker.setDisplayedValues(null);
mDistrictPicker.setMaxValue(mDistrictArray.length - 1); //設置最大值
mDistrictPicker.setDisplayedValues(mDistrictArray);
}
});
}
if (mDistrictPicker != null) {
mDistrictPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
/**
* 每當選擇的值改變時都會調用一次
* @param oldVal 改變前的值
* @param newVal 改變後的值
*/
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
mCurSelDistrict = mDistrictArray[picker.getValue()];
}
});
}
}
/**
* 顯示時間選擇器
*
* @param view
*/
public void show(View view) {
this.setOutsideTouchable(true);
this.showAtLocation(view, Gravity.BOTTOM, 0, 0);
setAlpha(0.3f);
}
/**
* 改變背景透明度
*
* @param value
*/
private void setAlpha(Float value) {
WindowManager.LayoutParams layoutParams = ((Activity) mContext).getWindow().getAttributes();
layoutParams.alpha = value;
((Activity) mContext).getWindow().setAttributes(layoutParams);
}
/**
* 設置左邊文本的內容
*
* @param o
*/
public void setLeftTextContent(Object o) {
if (mTvCancel == null)
return;
if (o instanceof String)
mTvCancel.setText((String) o);
else if (o instanceof Integer)
mTvCancel.setText((Integer) o);
else
mTvCancel.setText(mStrLeft);
}
/**
* 設置左邊文本的內容
*
* @param o
*/
public void setRightTextContent(Object o) {
if (mTvConfirm == null)
return;
if (o instanceof String)
mTvConfirm.setText((String) o);
else if (o instanceof Integer)
mTvConfirm.setText((Integer) o);
else
mTvConfirm.setText(mStrRight);
}
private JSONObject getAddressResult() {
JSONObject object = new JSONObject();
if (!TextUtils.isEmpty(mCurSelProvince) || !TextUtils.isEmpty(mCurSelCity) || !TextUtils.isEmpty(mCurSelDistrict)) {
try {
object.put("province", mCurSelProvince);
object.put("city", mCurSelCity);
object.put("district", mCurSelDistrict);
} catch (JSONException e) {
e.printStackTrace();
}
}
return object;
}
/**
* 設置選中後的返回數據,以json數據的形式返回
*
* @return
*/
private JSONObject getResult() {
//數據回調
int yearPos = mYearPicker.getValue();
int monthPos = mMonthPicker.getValue();
int dayPos = mDayPicker.getValue();
int hourPos = mHourPicker.getValue();
int minutePos = mMinutePicker.getValue();
int secondPos = mSecondPicker.getValue();
JSONObject object = new JSONObject();
try {
switch (mType) {
case 1:
object.put("year", mYearNumList.get(yearPos).toString());
object.put("month", mMonthNumList.get(monthPos).toString());
object.put("day", mDayNumList.get(dayPos).toString());
object.put("hour", mHourNumList.get(hourPos).toString());
object.put("minute", mMinuteNumList.get(minutePos).toString());
object.put("second", mSecondNumList.get(secondPos).toString());
break;
case 2:
object.put("year", mYearNumList.get(yearPos).toString());
object.put("month", mMonthNumList.get(monthPos).toString());
object.put("day", mDayNumList.get(dayPos).toString());
object.put("hour", mHourNumList.get(hourPos).toString());
object.put("minute", mMinuteNumList.get(minutePos).toString());
break;
case 3:
object.put("year", mYearNumList.get(yearPos).toString());
object.put("month", mMonthNumList.get(monthPos).toString());
object.put("day", mDayNumList.get(dayPos).toString());
object.put("hour", mHourNumList.get(hourPos).toString());
break;
case 4:
object.put("year", mYearNumList.get(yearPos).toString());
object.put("month", mMonthNumList.get(monthPos).toString());
object.put("day", mDayNumList.get(dayPos).toString());
break;
case 5:
object.put("hour", mHourNumList.get(hourPos).toString());
object.put("minute", mMinuteNumList.get(minutePos).toString());
object.put("second", mSecondNumList.get(secondPos).toString());
case 6:
object.put("hour", mHourNumList.get(hourPos).toString());
object.put("minute", mMinuteNumList.get(minutePos).toString());
break;
}
} catch (JSONException e) {
e.printStackTrace();
}
return object;
}
@SuppressLint("DefaultLocale")
private void initData(int type) {
//根據type現實ui__1年月日時分秒,2年月日時分 3年月日時,4年月日,5時分秒,6時分
switch (type) {
case 2:
mSecondPicker.setVisibility(View.GONE);
break;
case 3:
mMinutePicker.setVisibility(View.GONE);
mSecondPicker.setVisibility(View.GONE);
break;
case 4:
mHourPicker.setVisibility(View.GONE);
mMinutePicker.setVisibility(View.GONE);
mSecondPicker.setVisibility(View.GONE);
break;
case 5:
mYearPicker.setVisibility(View.GONE);
mMonthPicker.setVisibility(View.GONE);
mDayPicker.setVisibility(View.GONE);
break;
case 6:
mYearPicker.setVisibility(View.GONE);
mMonthPicker.setVisibility(View.GONE);
mDayPicker.setVisibility(View.GONE);
mHourPicker.setVisibility(View.GONE);
break;
}
//數據集合初始化
//年
Calendar startCal = Calendar.getInstance();
startCal.setTimeInMillis(0);
Calendar curCal = Calendar.getInstance();
int startYear = startCal.get(Calendar.YEAR);
int endYear = curCal.get(Calendar.YEAR);
for (int i = endYear; i >= startYear; i--) {
mYearList.add(i + "年");
mYearNumList.add(i);
}
//月
for (int i = 1; i <= 12; i++) {
mMonthList.add(String.format("%02d", i) + "月");
mMonthNumList.add(i);
}
//日
int curDay = curCal.getActualMaximum(Calendar.DAY_OF_MONTH);//當前月份有多少天
for (int i = 1; i <= curDay; i++) {
mDayList.add(String.format("%02d", i) + "日");
mDayNumList.add(i);
}
//時
for (int i = 1; i <= 24; i++) {
mHourList.add(String.format("%02d", i) + "時");
mHourNumList.add(i);
}
//分
for (int i = 1; i <= 60; i++) {
mMinuteList.add(String.format("%02d", i) + "分");
mMinuteNumList.add(i);
}
//秒
for (int i = 1; i <= 60; i++) {
mSecondList.add(String.format("%02d", i) + "秒");
mSecondNumList.add(i);
}
//設置數據----------------------------------------------------------
//獲取當前初始化數據__月日時分秒
int cMonth = curCal.get(Calendar.MONTH);//從0開始
int cDay = curCal.get(Calendar.DATE) - 1;//日
int cHour = curCal.get(Calendar.HOUR_OF_DAY) - 1;//時
int cMinute = curCal.get(Calendar.MINUTE) - 1;//分
int cSecond = curCal.get(Calendar.SECOND) - 1;//秒
mYearPicker.setDisplayedValues(mYearList.toArray(new String[0]));
mYearPicker.setMaxValue(mYearList.size() - 1); //設置最大值
mYearPicker.setWrapSelectorWheel(true);
mYearPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mMonthPicker.setDisplayedValues(mMonthList.toArray(new String[0]));
mMonthPicker.setMaxValue(mMonthList.size() - 1); //設置最大值
mMonthPicker.setWrapSelectorWheel(true);
mMonthPicker.setValue(cMonth);
mMonthPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mDayPicker.setDisplayedValues(mDayList.toArray(new String[0]));
mDayPicker.setMaxValue(mDayList.size() - 1); //設置最大值
mDayPicker.setWrapSelectorWheel(true);
mDayPicker.setValue(cDay);
mDayPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mHourPicker.setDisplayedValues(mHourList.toArray(new String[0]));
mHourPicker.setMaxValue(mHourList.size() - 1); //設置最大值
mHourPicker.setWrapSelectorWheel(true);
mHourPicker.setValue(cHour);
mHourPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mMinutePicker.setDisplayedValues(mMinuteList.toArray(new String[0]));
mMinutePicker.setMaxValue(mMinuteList.size() - 1); //設置最大值
mMinutePicker.setWrapSelectorWheel(true);
mMinutePicker.setValue(cMinute);
mMinutePicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mSecondPicker.setDisplayedValues(mSecondList.toArray(new String[0]));
mSecondPicker.setMaxValue(mSecondList.size() - 1); //設置最大值
mSecondPicker.setWrapSelectorWheel(true);
mSecondPicker.setValue(cSecond);
mSecondPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
}
private void getAddressData(Context context, String path) {
List<AddressInfo> result = readXmlBySAX(context, path);
//數據轉換
if (result != null) {
for (AddressInfo cache : result) {
mProvinceList.add(cache.getProvince());
mCityMap.putAll(cache.getCityMap());
mDistrictMap.putAll(cache.getDistrictMap());
}
}
//轉換完成__設置數據
//省份
provinceStrArray = mProvinceList.toArray(new String[0]);
mProvincePicker.setDisplayedValues(provinceStrArray);
mProvincePicker.setMaxValue(provinceStrArray.length - 1); //設置最大值,最大值是datas[3]
mProvincePicker.setWrapSelectorWheel(true);
mProvincePicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mCurSelProvince = provinceStrArray[0];
//城市
mCityArray = mCityMap.get(mCurSelProvince).toArray(new String[0]);
mCityPicker.setDisplayedValues(mCityArray);
mCityPicker.setMaxValue(mCityArray.length - 1); //設置最大值
mCityPicker.setWrapSelectorWheel(true);
mCityPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mCurSelCity = mCityArray[0];
//市區
mDistrictArray = mDistrictMap.get(mCurSelCity).toArray(new String[0]);
mDistrictPicker.setDisplayedValues(mDistrictArray);
mDistrictPicker.setMaxValue(mDistrictArray.length - 1); //設置最大值
mDistrictPicker.setWrapSelectorWheel(true);
mDistrictPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); //禁止輸入
mCurSelDistrict = mDistrictArray[0];
}
private List<AddressInfo> readXmlBySAX(Context context, String path) {
try {
InputStream in = context.getResources().getAssets().open(path);
//【創建解析器】
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
AddressSaxHandler handler = new AddressSaxHandler();
saxParser.parse(in, handler);
in.close();
return handler.getResult();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 自定義NumberPicker ---------------------------------------------------------------
*/
public class DivNumberPicker extends NumberPicker {
public DivNumberPicker(Context context) {
super(context);
}
public DivNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DivNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void addView(View child) {
super.addView(child);
updateView(child);
}
@Override
public void addView(View child, int index,
android.view.ViewGroup.LayoutParams params) {
super.addView(child, index, params);
updateView(child);
}
@Override
public void addView(View child, android.view.ViewGroup.LayoutParams params) {
super.addView(child, params);
updateView(child);
}
public void updateView(View view) {
if (view instanceof EditText) {
//這裏修改顯示字體的屬性,主要修改顏色
((EditText) view).setTextSize(12);
((EditText) view).setTextColor(Color.BLACK);
}
}
@Override
public void setDisplayedValues(String[] displayedValues) {
super.setDisplayedValues(displayedValues);
setNumberPickerDividerColor(this);
}
//設置分割線的顏色值
private void setNumberPickerDividerColor(NumberPicker numberPicker) {
Field[] pickerFields = NumberPicker.class.getDeclaredFields();
for (Field pf : pickerFields) {
if (pf.getName().equals("mSelectionDivider")) {
pf.setAccessible(true);
try {
//設置分割線的顏色值 透明
pf.set(numberPicker, new ColorDrawable(Color.BLUE));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
break;
}
}
}
}
/**
* author:li
* date:2020/6/21
* desc:地址model:xml解釋 --------------------------------------------------------------
*/
public class AddressSaxHandler extends DefaultHandler {
//解釋結果結合
private List<AddressInfo> result;
private AddressInfo mCurrentInfo;
private String mCurrentProvince = "";
private String mCurrentCity = "";
private String mTagName = "";
List<AddressInfo> getResult() {
return result;
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
result = new ArrayList<>();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (localName.equals("province")) {
mCurrentInfo = new AddressInfo();
mCurrentInfo.setProvince(attributes.getValue("name"));
mCurrentProvince = mCurrentInfo.getProvince();
} else if (localName.equals("city")) {
mCurrentCity = attributes.getValue("name");
List<String> cityList = new ArrayList<>();
if (mCurrentInfo.getCityMap().get(mCurrentProvince) == null) {
cityList.add(mCurrentCity);
mCurrentInfo.getCityMap().put(mCurrentProvince, cityList);
} else {
cityList = mCurrentInfo.getCityMap().get(mCurrentProvince);
cityList.add(mCurrentCity);
mCurrentInfo.getCityMap().put(mCurrentProvince, cityList);
}
}
mTagName = localName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
if (!TextUtils.isEmpty(mTagName)) {
String data = new String(ch, start, length);
if (mTagName.equals("district")) {
List<String> districtList = new ArrayList<>();
if (mCurrentInfo.getDistrictMap().get(mCurrentCity) == null) {
districtList.add(data);
mCurrentInfo.getDistrictMap().put(mCurrentCity, districtList);
} else {
districtList = mCurrentInfo.getDistrictMap().get(mCurrentCity);
districtList.add(data);
mCurrentInfo.getDistrictMap().put(mCurrentCity, districtList);
}
}
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (localName.equals("province")) {
result.add(mCurrentInfo);
}
this.mTagName = null;
}
}
/**
* 地址實體類 ------------------------------------------------------------
*/
class AddressInfo {
private String province;
private Map<String, List<String>> cityMap = new HashMap<>();
private Map<String, List<String>> districtMap = new HashMap<>();
String getProvince() {
return province;
}
void setProvince(String province) {
this.province = province;
}
Map<String, List<String>> getCityMap() {
return cityMap;
}
public void setCityMap(Map<String, List<String>> cityMap) {
this.cityMap = cityMap;
}
Map<String, List<String>> getDistrictMap() {
return districtMap;
}
public void setDistrictMap(Map<String, List<String>> districtMap) {
this.districtMap = districtMap;
}
}
/**
* 定義回調接口 ----------------------------------------------------------------------
*/
public interface ClickCallBack {
void cancel();
void confirm(JSONObject jsonObject);
}
public void setmClickCallBack(ClickCallBack mClickCallBack) {
this.mClickCallBack = mClickCallBack;
}
}