Android仿IOS三级级联城市选择器

来源:互联网 发布:centos识别不到硬盘 编辑:程序博客网 时间:2024/05/22 09:43

项目用到城市选择,就找了一个大神的代码,自己做了修改后使用的,本程序有两个地方不是很完美:

一、点击popupWindow空白的区域不能关闭popupWindow;

二、选择器那里,不是当前选中的值,不能做到类似IOS里面的折叠,就是类似滚轮的那种立体效果。

望路过的大神们可以加以完善下。

上代码:popup_select_city.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical">    <LinearLayout        android:orientation="vertical"         android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="@color/white"        android:layout_alignParentBottom="true">    <RelativeLayout        android:orientation="horizontal"        android:layout_width="match_parent"        android:layout_height="44dp"        android:paddingLeft="10dp"        android:paddingRight="10dp">        <Button            android:id="@+id/btn_cancel"            android:layout_width="66dp"            android:layout_height="match_parent"            android:text="取消"            android:layout_alignParentLeft="true"            android:textSize="18sp"            android:textColor="#4a8ff8"            android:gravity="center"            />        <Button            android:id="@+id/btn_confirm"            android:layout_width="66dp"            android:layout_height="match_parent"            android:text="确定"            android:layout_alignParentRight="true"            android:textSize="18sp"            android:textColor="@color/tab_select"            android:gravity="center"            />        <EditText             android:id="@+id/edt_city_select"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_toRightOf="@id/btn_cancel"            android:layout_toLeftOf="@id/btn_confirm"            android:padding="5dp"            android:layout_centerVertical="true"            android:hint="请输入省、市、区(县)"            android:background="@drawable/border_corner_edit"            android:textSize="14sp"/>    </RelativeLayout><LinearLayout        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <kankan.wheel.widget.WheelView            android:id="@+id/id_province"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1" >        </kankan.wheel.widget.WheelView>        <kankan.wheel.widget.WheelView            android:id="@+id/id_city"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1" >        </kankan.wheel.widget.WheelView>        <kankan.wheel.widget.WheelView            android:id="@+id/id_district"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1" >        </kankan.wheel.widget.WheelView>    </LinearLayout>    </LinearLayout></RelativeLayout>

selectCity.java:

package com.shengping.pao.PopupWindow;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.json.JSONObject;import kankan.wheel.widget.WheelView;import kankan.wheel.widget.OnWheelChangedListener;import kankan.wheel.widget.adapters.ArrayWheelAdapter;import com.shengping.pao.R;import com.shengping.pao.model.CityModel;import com.shengping.pao.model.DistrictModel;import com.shengping.pao.model.ProvinceModel;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.content.res.AssetManager;import android.graphics.drawable.BitmapDrawable;import android.text.Editable;import android.text.TextWatcher;import android.view.Gravity;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.view.ViewGroup;import android.view.WindowManager;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.PopupWindow;public class Select_City implements OnClickListener, OnWheelChangedListener{ private Context context; private View parentView; /**     * 取消按钮     */private Button btnCancel;    /**     * 确定按钮     */private Button btnConfirm;private PopupWindow popupWindow;private WheelView mViewProvince;private WheelView mViewCity;private WheelView mViewDistrict;/** * 所有省 */protected String[] mProvinceDatas;/** * key - 省 value - 市 */protected Map<String, String[]> mCitisDatasMap = new HashMap<String, String[]>();/** * key - 市 values - 区 */protected Map<String, String[]> mDistrictDatasMap = new HashMap<String, String[]>();/** * key - 区 values - 邮编 */protected Map<String, String> mZipcodeDatasMap = new HashMap<String, String>(); /** * 当前省的名称 */protected String mCurrentProviceName;/** * 当前市的名称 */protected String mCurrentCityName;/** * 当前区的名称 */protected String mCurrentDistrictName ="";/** * 当前区的邮政编码 */protected String mCurrentZipCode ="";private View view;private cityselectListener listener;public Select_City(Context activity,View v){    this.context = activity;    parentView=v;}    @SuppressWarnings("deprecation")@SuppressLint("InflateParams")public Select_City builder(){        // PopView        view = LayoutInflater.from(context).inflate(                R.layout.popup_select_city, null);        initView(view);// android.view.View#getWindowToken()        popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);        popupWindow.setBackgroundDrawable(new BitmapDrawable());        popupWindow.setOutsideTouchable(true);        popupWindow.setFocusable(true);        popupWindow.setTouchInterceptor(new OnTouchListener() {        @SuppressLint("ClickableViewAccessibility")@Override    public boolean onTouch(View v, MotionEvent event) {//    System.out.println("touch:"+event.getAction());    if(event.getAction()==MotionEvent.ACTION_OUTSIDE){    popupWindow.dismiss();    return true;    }    return false;    }    });        popupWindow.setOnDismissListener(new PopDismissListener());        popupWindow.setAnimationStyle(R.style.PopAnimationDownUp);        return this;    }    public  void initView(View contentView){    mViewProvince = (WheelView) contentView.findViewById(R.id.id_province);mViewCity = (WheelView) contentView.findViewById(R.id.id_city);mViewDistrict = (WheelView)contentView. findViewById(R.id.id_district);btnConfirm = (Button)contentView. findViewById(R.id.btn_confirm);btnCancel=(Button)contentView. findViewById(R.id.btn_cancel);// 添加change事件    mViewProvince.addChangingListener(this);    // 添加change事件    mViewCity.addChangingListener(this);    // 添加change事件    mViewDistrict.addChangingListener(this);    // 添加onclick事件    btnConfirm.setOnClickListener(this);    btnCancel.setOnClickListener(this);        initProvinceDatas();mViewProvince.setViewAdapter(new ArrayWheelAdapter<String>(context, mProvinceDatas));// 设置可见条目数量mViewProvince.setVisibleItems(7);mViewCity.setVisibleItems(7);mViewDistrict.setVisibleItems(7);updateCities();updateAreas();EditText edt_search=(EditText)contentView.findViewById(R.id.edt_city_select);edt_search.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}@Overridepublic void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {// TODO Auto-generated method stub}@Overridepublic void afterTextChanged(Editable arg0) {String str=arg0.toString();int i=0;if(str.equals("")){mViewProvince.setCurrentItem(i);return ;}for(String provence:mProvinceDatas){if(provence.contains(str)){mViewProvince.setCurrentItem(i);return;}i++;}int privenceIndex=0;int cityIndex=0;int districtIndex=0;for(privenceIndex=0;privenceIndex<mProvinceDatas.length;privenceIndex++){String[] citys=mCitisDatasMap.get(mProvinceDatas[privenceIndex]);cityIndex=0;   for(String city:citys){   if(city.contains(str)){   mViewProvince.setCurrentItem(privenceIndex);   mViewCity.setCurrentItem(cityIndex);   return;   }   cityIndex++;   }}  privenceIndex=0;  cityIndex=0;  for(privenceIndex=0;privenceIndex<mProvinceDatas.length;privenceIndex++){String[] citys=mCitisDatasMap.get(mProvinceDatas[privenceIndex]);cityIndex=0;   for(String city:citys){   String[] districts=mDistrictDatasMap.get(city);   districtIndex=0;   for(String district:districts){   if(district.contains(str)){   mViewProvince.setCurrentItem(privenceIndex);   mViewCity.setCurrentItem(cityIndex);   mViewDistrict.setCurrentItem(districtIndex);   if(districtIndex==0){   mCurrentDistrictName = district;mCurrentZipCode = mZipcodeDatasMap.get(mCurrentDistrictName);   }   return;   }   districtIndex++;   }   cityIndex++;   }}  }});    }    /**     * 显示     */    @SuppressLint("NewApi")public void show(){        if (null != popupWindow){            setBackgroundAlpha(0.5f);        popupWindow.showAtLocation(parentView, Gravity.BOTTOM,0,0);        }    }    /**     * 撤销     */    public void dismiss(){        if (null != popupWindow){            popupWindow.dismiss();        }    }    /**     * 设置背景透明度     * @param alpha 背景的Alpha     */    private void setBackgroundAlpha(float alpha){        WindowManager.LayoutParams lp =  ((Activity)context).getWindow().getAttributes();        lp.alpha = alpha;        ((Activity)context).getWindow().setAttributes(lp);    }    private class PopDismissListener implements PopupWindow.OnDismissListener{        @Override        public void onDismiss() {            //更改背景透明度            setBackgroundAlpha(1.0f);        }    }@Overridepublic void onClick(View v) {if(v.getId()==R.id.btn_cancel){dismiss();}else if(v.getId()==R.id.btn_confirm){if(listener!=null){JSONObject json=new JSONObject();try{json.put("mCurrentProviceName", mCurrentProviceName);json.put("mCurrentCityName", mCurrentCityName);json.put("mCurrentDistrictName", mCurrentDistrictName);}catch(Exception e){e.printStackTrace();}listener.selectok(json);dismiss();}}}@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {if (wheel == mViewProvince) {updateCities();} else if (wheel == mViewCity) {updateAreas();} else if (wheel == mViewDistrict) {mCurrentDistrictName = mDistrictDatasMap.get(mCurrentCityName)[newValue];mCurrentZipCode = mZipcodeDatasMap.get(mCurrentDistrictName);}}/** * 解析省市区的XML数据 */    protected void initProvinceDatas(){List<ProvinceModel> provinceList = null;    AssetManager asset = context.getAssets();        try {            InputStream input = asset.open("province_data.xml");            // 创建一个解析xml的工厂对象SAXParserFactory spf = SAXParserFactory.newInstance();// 解析xmlSAXParser parser = spf.newSAXParser();XmlParserHandler handler = new XmlParserHandler();parser.parse(input, handler);input.close();// 获取解析出来的数据provinceList = handler.getDataList();//*/ 初始化默认选中的省、市、区if (provinceList!= null && !provinceList.isEmpty()) {mCurrentProviceName = provinceList.get(0).getName();List<CityModel> cityList = provinceList.get(0).getCityList();if (cityList!= null && !cityList.isEmpty()) {mCurrentCityName = cityList.get(0).getName();List<DistrictModel> districtList = cityList.get(0).getDistrictList();mCurrentDistrictName = districtList.get(0).getName();mCurrentZipCode = districtList.get(0).getZipcode();}}//*/mProvinceDatas = new String[provinceList.size()];        for (int i=0; i< provinceList.size(); i++) {        // 遍历所有省的数据        mProvinceDatas[i] = provinceList.get(i).getName();        List<CityModel> cityList = provinceList.get(i).getCityList();        String[] cityNames = new String[cityList.size()];        for (int j=0; j< cityList.size(); j++) {        // 遍历省下面的所有市的数据        cityNames[j] = cityList.get(j).getName();        List<DistrictModel> districtList = cityList.get(j).getDistrictList();        String[] distrinctNameArray = new String[districtList.size()];        DistrictModel[] distrinctArray = new DistrictModel[districtList.size()];        for (int k=0; k<districtList.size(); k++) {        // 遍历市下面所有区/县的数据        DistrictModel districtModel = new DistrictModel(districtList.get(k).getName(), districtList.get(k).getZipcode());        // 区/县对于的邮编,保存到mZipcodeDatasMap        mZipcodeDatasMap.put(districtList.get(k).getName(), districtList.get(k).getZipcode());        distrinctArray[k] = districtModel;        distrinctNameArray[k] = districtModel.getName();        }        // 市-区/县的数据,保存到mDistrictDatasMap        mDistrictDatasMap.put(cityNames[j], distrinctNameArray);        }        // 省-市的数据,保存到mCitisDatasMap        mCitisDatasMap.put(provinceList.get(i).getName(), cityNames);        }        } catch (Throwable e) {              e.printStackTrace();          } finally {                } }/** * 根据当前的省,更新市WheelView的信息 */private void updateCities() {int pCurrent = mViewProvince.getCurrentItem();mCurrentProviceName = mProvinceDatas[pCurrent];String[] cities = mCitisDatasMap.get(mCurrentProviceName);if (cities == null) {cities = new String[] { "" };}mViewCity.setViewAdapter(new ArrayWheelAdapter<String>(context, cities));mViewCity.setCurrentItem(0);updateAreas();}/** * 根据当前的市,更新区WheelView的信息 */private void updateAreas() {int pCurrent = mViewCity.getCurrentItem();mCurrentCityName = mCitisDatasMap.get(mCurrentProviceName)[pCurrent];String[] areas = mDistrictDatasMap.get(mCurrentCityName);if (areas == null) {areas = new String[] { "" };}mViewDistrict.setViewAdapter(new ArrayWheelAdapter<String>(context, areas));mViewDistrict.setCurrentItem(0);}public interface cityselectListener{public void selectok(JSONObject json);}public cityselectListener getListener() {return listener;}public void setListener(cityselectListener listener) {this.listener = listener;}}
XmlParserHandler.java

package com.shengping.pao.PopupWindow;import java.util.ArrayList;import java.util.List;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import com.shengping.pao.model.CityModel;import com.shengping.pao.model.DistrictModel;import com.shengping.pao.model.ProvinceModel;public class XmlParserHandler extends DefaultHandler {/** * 存储所有的解析对象 */private List<ProvinceModel> provinceList = new ArrayList<ProvinceModel>();   public XmlParserHandler() {}public List<ProvinceModel> getDataList() {return provinceList;}@Overridepublic void startDocument() throws SAXException {// 当读到第一个开始标签的时候,会触发这个方法}ProvinceModel provinceModel = new ProvinceModel();CityModel cityModel = new CityModel();DistrictModel districtModel = new DistrictModel();@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// 当遇到开始标记的时候,调用这个方法if (qName.equals("province")) {provinceModel = new ProvinceModel();provinceModel.setName(attributes.getValue(0));provinceModel.setCityList(new ArrayList<CityModel>());} else if (qName.equals("city")) {cityModel = new CityModel();cityModel.setName(attributes.getValue(0));cityModel.setDistrictList(new ArrayList<DistrictModel>());} else if (qName.equals("district")) {districtModel = new DistrictModel();districtModel.setName(attributes.getValue(0));districtModel.setZipcode(attributes.getValue(1));}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// 遇到结束标记的时候,会调用这个方法if (qName.equals("district")) {cityModel.getDistrictList().add(districtModel);        } else if (qName.equals("city")) {        provinceModel.getCityList().add(cityModel);        } else if (qName.equals("province")) {        provinceList.add(provinceModel);        }}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {}}

CityModel.java

package com.shengping.pao.model;import java.util.List;public class CityModel {private String name;private List<DistrictModel> districtList;public CityModel() {super();}public CityModel(String name, List<DistrictModel> districtList) {super();this.name = name;this.districtList = districtList;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<DistrictModel> getDistrictList() {return districtList;}public void setDistrictList(List<DistrictModel> districtList) {this.districtList = districtList;}@Overridepublic String toString() {return "CityModel [name=" + name + ", districtList=" + districtList+ "]";}}

DistrictModel.java

package com.shengping.pao.model;public class DistrictModel {private String name;private String zipcode;public DistrictModel() {super();}public DistrictModel(String name, String zipcode) {super();this.name = name;this.zipcode = zipcode;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getZipcode() {return zipcode;}public void setZipcode(String zipcode) {this.zipcode = zipcode;}@Overridepublic String toString() {return "DistrictModel [name=" + name + ", zipcode=" + zipcode + "]";}}

ProvinceModel.java

package com.shengping.pao.model;import java.util.List;public class ProvinceModel {private String name;private List<CityModel> cityList;public ProvinceModel() {super();}public ProvinceModel(String name, List<CityModel> cityList) {super();this.name = name;this.cityList = cityList;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<CityModel> getCityList() {return cityList;}public void setCityList(List<CityModel> cityList) {this.cityList = cityList;}@Overridepublic String toString() {return "ProvinceModel [name=" + name + ", cityList=" + cityList + "]";}}


使用者只要实现 citiyselectListener接口,即可监听“完成”按钮事件  并获取当前选中的值:

Select_City select_city=new Select_City(getContext(),contentView);

select_city=select_city.builder();

select_city.setListener(listener);

select_city.show();



0 0
原创粉丝点击