自定义三级联动列表选择省市区

在进行三级联动的时候我们需要先进行调用网络接口去获取数据,然后将获取到的数据放到我们所自定义的条件选择器当中,所以我们需要先引入相应的jar包

implementation 'liji.library.dev:citypickerview:0.7.0'
public class MyCityPicker implements CanShow, OnWheelChangedListener {
    private Context context;

    private PopupWindow popwindow;

    private View popview;

    private WheelView mViewProvince;

    private WheelView mViewCity;

    private WheelView mViewDistrict;

    private RelativeLayout mRelativeTitleBg;

    private TextView mTvOK;

    private TextView mTvTitle;

    private TextView mTvCancel;

    /**
     * 所有省
     */
    protected List mProvinceDatas;

    /**
     * key - 省 value - 市
     */
    protected Map> mCitisDatasMap = new HashMap<>();

    /**
     * key - 市 values - 区
     */
    protected Map> mDistrictDatasMap = new HashMap<>();


    /**
     * 当前省的名称
     */
    protected String mCurrentProviceId;

    /**
     * 当前市的名称
     */
    protected String mCurrentCityId;

    /**
     * 当前区的名称
     */
    protected String mCurrentDistrictId = "";


    private OnCityItemClickListener listener;

    public interface OnCityItemClickListener {
        void onSelected(int... citySelected);
    }

    public void setOnCityItemClickListener(OnCityItemClickListener listener) {
        this.listener = listener;
    }

    /**
     * Default text color
     */
    public static final int DEFAULT_TEXT_COLOR = 0xFF585858;

    /**
     * Default text size
     */
    public static final int DEFAULT_TEXT_SIZE = 18;

    // Text settings
    private int textColor = DEFAULT_TEXT_COLOR;

    private int textSize = DEFAULT_TEXT_SIZE;

    /**
     * 滚轮显示的item个数
     */
    private static final int DEF_VISIBLE_ITEMS = 5;

    // Count of visible items
    private int visibleItems = DEF_VISIBLE_ITEMS;

    /**
     * 省滚轮是否循环滚动
     */
    private boolean isProvinceCyclic = false;

    /**
     * 市滚轮是否循环滚动
     */
    private boolean isCityCyclic = true;

    /**
     * 区滚轮是否循环滚动
     */
    private boolean isDistrictCyclic = true;

    /**
     * item间距
     */
    private int padding = 5;


    /**
     * Color.BLACK
     */
    private String cancelTextColorStr = "#000000";


    /**
     * Color.BLUE
     */
    private String confirmTextColorStr = "#0000FF";

    /**
     * 标题背景颜色
     */
    private String titleBackgroundColorStr = "#E9E9E9";


    /**
     * 两级联动
     */
    private boolean showProvinceAndCity = false;

    /**
     * 标题
     */
    private String mTitle = "选择地区";

    private MyCityPicker(Builder builder) {
        this.textColor = builder.textColor;
        this.textSize = builder.textSize;
        this.visibleItems = builder.visibleItems;
        this.isProvinceCyclic = builder.isProvinceCyclic;
        this.isDistrictCyclic = builder.isDistrictCyclic;
        this.isCityCyclic = builder.isCityCyclic;
        this.context = builder.mContext;
        this.padding = builder.padding;
//      this.mTitle = builder.mTitle;
        this.titleBackgroundColorStr = builder.titleBackgroundColorStr;
        this.confirmTextColorStr = builder.confirmTextColorStr;
        this.cancelTextColorStr = builder.cancelTextColorStr;

        this.showProvinceAndCity = builder.showProvinceAndCity;

        LayoutInflater layoutInflater = LayoutInflater.from(context);
        popview = layoutInflater.inflate(R.layout.pop_my_citypicker, null);

        mViewProvince = (WheelView) popview.findViewById(com.lljjcoder.citypickerview.R.id.id_province);
        mViewCity = (WheelView) popview.findViewById(com.lljjcoder.citypickerview.R.id.id_city);
        mViewDistrict = (WheelView) popview.findViewById(com.lljjcoder.citypickerview.R.id.id_district);
        mRelativeTitleBg = (RelativeLayout) popview.findViewById(com.lljjcoder.citypickerview.R.id.rl_title);
        mTvOK = (TextView) popview.findViewById(com.lljjcoder.citypickerview.R.id.tv_confirm);
        mTvTitle = (TextView) popview.findViewById(com.lljjcoder.citypickerview.R.id.tv_title);
        mTvCancel = (TextView) popview.findViewById(com.lljjcoder.citypickerview.R.id.tv_cancel);


        popwindow = new PopupWindow(popview, LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);
        popwindow.setBackgroundDrawable(new ColorDrawable(0x80000000));
        popwindow.setAnimationStyle(com.lljjcoder.citypickerview.R.style.AnimBottom);
        popwindow.setTouchable(true);
        popwindow.setOutsideTouchable(true);
        popwindow.setFocusable(true);


        /**
         * 设置标题背景颜色
         */
        if (!TextUtils.isEmpty(this.titleBackgroundColorStr)) {
            mRelativeTitleBg.setBackgroundColor(Color.parseColor(this.titleBackgroundColorStr));
        }

        /**
         * 设置标题
         */
        if (!TextUtils.isEmpty(this.mTitle)) {
            mTvTitle.setText(this.mTitle);
        }

        //设置确认按钮文字颜色
        if (!TextUtils.isEmpty(this.confirmTextColorStr)) {
            mTvOK.setTextColor(Color.parseColor(this.confirmTextColorStr));
        }

        //设置取消按钮文字颜色
        if (!TextUtils.isEmpty(this.cancelTextColorStr)) {
            mTvCancel.setTextColor(Color.parseColor(this.cancelTextColorStr));
        }


        //只显示省市两级联动
        if (this.showProvinceAndCity) {
            mViewDistrict.setVisibility(View.GONE);
        } else {
            mViewDistrict.setVisibility(View.VISIBLE);
        }

        // 添加change事件
        mViewProvince.addChangingListener(this);
        // 添加change事件
        mViewCity.addChangingListener(this);
        // 添加change事件
        mViewDistrict.addChangingListener(this);
        // 添加onclick事件
        mTvCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hide();
            }
        });
        mTvOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    if (showProvinceAndCity) {
                        listener.onSelected(mViewProvince.getCurrentItem(), mViewCity.getCurrentItem(), 0);
                    } else {
                        listener.onSelected(mViewProvince.getCurrentItem(), mViewCity.getCurrentItem(), mViewDistrict.getCurrentItem());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                hide();
            }
        });

    }

    public static class Builder {
        /**
         * Default text color
         */
        public static final int DEFAULT_TEXT_COLOR = 0xFF585858;

        /**
         * Default text size
         */
        public static final int DEFAULT_TEXT_SIZE = 18;

        // Text settings
        private int textColor = DEFAULT_TEXT_COLOR;

        private int textSize = DEFAULT_TEXT_SIZE;

        /**
         * 滚轮显示的item个数
         */
        private static final int DEF_VISIBLE_ITEMS = 5;

        // Count of visible items
        private int visibleItems = DEF_VISIBLE_ITEMS;

        /**
         * 省滚轮是否循环滚动
         */
        private boolean isProvinceCyclic = false;

        /**
         * 市滚轮是否循环滚动
         */
        private boolean isCityCyclic = true;

        /**
         * 区滚轮是否循环滚动
         */
        private boolean isDistrictCyclic = true;

        private Context mContext;

        /**
         * item间距
         */
        private int padding = 5;


        /**
         * Color.BLACK
         */
        private String cancelTextColorStr = "#000000";


        /**
         * Color.BLUE
         */
        private String confirmTextColorStr = "#0000FF";

        /**
         * 标题背景颜色
         */
        private String titleBackgroundColorStr = "#E9E9E9";


        /**
         * 标题
         */
        private String mTitle = "选择地区";

        /**
         * 两级联动
         */
        private boolean showProvinceAndCity = false;

        public Builder(Context context) {
            this.mContext = context;
        }

        /**
         * 设置标题背景颜色
         *
         * @param colorBg
         * @return
         */
        public Builder titleBackgroundColor(String colorBg) {
            this.titleBackgroundColorStr = colorBg;
            return this;
        }

        /**
         * 设置标题
         *
         * @param mtitle
         * @return
         */
        public Builder title(String mtitle) {
            this.mTitle = mtitle;
            return this;
        }

        /**
         * 是否只显示省市两级联动
         *
         * @param flag
         * @return
         */
        public Builder onlyShowProvinceAndCity(boolean flag) {
            this.showProvinceAndCity = flag;
            return this;
        }


        //        /**
        //         * 确认按钮文字颜色
        //         * @param color
        //         * @return
        //         */
        //        public Builder confirTextColor(int color) {
        //            this.confirmTextColor = color;
        //            return this;
        //        }

        /**
         * 确认按钮文字颜色
         *
         * @param color
         * @return
         */
        public Builder confirTextColor(String color) {
            this.confirmTextColorStr = color;
            return this;
        }

        //        /**
        //         * 取消按钮文字颜色
        //         * @param color
        //         * @return
        //         */
        //        public Builder cancelTextColor(int color) {
        //            this.cancelTextColor = color;
        //            return this;
        //        }

        /**
         * 取消按钮文字颜色
         *
         * @param color
         * @return
         */
        public Builder cancelTextColor(String color) {
            this.cancelTextColorStr = color;
            return this;
        }

        /**
         * item文字颜色
         *
         * @param textColor
         * @return
         */
        public Builder textColor(int textColor) {
            this.textColor = textColor;
            return this;
        }

        /**
         * item文字大小
         *
         * @param textSize
         * @return
         */
        public Builder textSize(int textSize) {
            this.textSize = textSize;
            return this;
        }

        /**
         * 滚轮显示的item个数
         *
         * @param visibleItems
         * @return
         */
        public Builder visibleItemsCount(int visibleItems) {
            this.visibleItems = visibleItems;
            return this;
        }

        /**
         * 省滚轮是否循环滚动
         *
         * @param isProvinceCyclic
         * @return
         */
        public Builder provinceCyclic(boolean isProvinceCyclic) {
            this.isProvinceCyclic = isProvinceCyclic;
            return this;
        }

        /**
         * 市滚轮是否循环滚动
         *
         * @param isCityCyclic
         * @return
         */
        public Builder cityCyclic(boolean isCityCyclic) {
            this.isCityCyclic = isCityCyclic;
            return this;
        }

        /**
         * 区滚轮是否循环滚动
         *
         * @param isDistrictCyclic
         * @return
         */
        public Builder districtCyclic(boolean isDistrictCyclic) {
            this.isDistrictCyclic = isDistrictCyclic;
            return this;
        }

        /**
         * item间距
         *
         * @param itemPadding
         * @return
         */
        public Builder itemPadding(int itemPadding) {
            this.padding = itemPadding;
            return this;
        }

        public MyCityPicker build() {
            MyCityPicker cityPicker = new MyCityPicker(this);
            return cityPicker;
        }

    }

    private void setUpData() {
        ProvinceWheelAdapter arrayWheelAdapter = new ProvinceWheelAdapter(context, mProvinceDatas);
        mViewProvince.setViewAdapter(arrayWheelAdapter);
        //获取所设置的省的位置,直接定位到该位置
        mViewProvince.setCurrentItem(0);
        // 设置可见条目数量
        mViewProvince.setVisibleItems(visibleItems);
        mViewCity.setVisibleItems(visibleItems);
        mViewDistrict.setVisibleItems(visibleItems);
        mViewProvince.setCyclic(isProvinceCyclic);
        mViewCity.setCyclic(isCityCyclic);
        mViewDistrict.setCyclic(isDistrictCyclic);
        arrayWheelAdapter.setPadding(padding);
        arrayWheelAdapter.setTextColor(textColor);
        arrayWheelAdapter.setTextSize(textSize);

        updateCities();
        updateAreas();
    }

    public List getmProvinceDatas() {
        return mProvinceDatas;
    }

    public Map> getmCitisDatasMap() {
        return mCitisDatasMap;
    }

    public Map> getmDistrictDatasMap() {
        return mDistrictDatasMap;
    }

    public void setmProvinceDatas(List mProvinceDatas) {
        this.mProvinceDatas = mProvinceDatas;
    }

    public void setmCitisDatasMap(Map> mCitisDatasMap) {
        this.mCitisDatasMap = mCitisDatasMap;
    }

    public void setmDistrictDatasMap(Map> mDistrictDatasMap) {
        this.mDistrictDatasMap = mDistrictDatasMap;
    }

    /**
     * 根据当前的市,更新区WheelView的信息
     */
    private void updateAreas() {
        int pCurrent = mViewCity.getCurrentItem();
        try {
            mCurrentCityId = mCitisDatasMap.get(mCurrentProviceId).get(pCurrent).getCityId();
        } catch (Exception e) {
            e.printStackTrace();
            mCurrentCityId = "";
        }
        List areas = mDistrictDatasMap.get(mCurrentCityId);

        if (areas == null) {
            areas = new ArrayList<>();
        }

        AreaWheelAdapter districtWheel = new AreaWheelAdapter(context, areas);
        // 设置可见条目数量
        districtWheel.setTextColor(textColor);
        districtWheel.setTextSize(textSize);
        mViewDistrict.setViewAdapter(districtWheel);
        mViewDistrict.setCurrentItem(0);
        //获取第一个区名称
        try {
            mCurrentDistrictId = mDistrictDatasMap.get(mCurrentCityId).get(0).getAreaId();
        } catch (Exception e) {
            e.printStackTrace();
            mCurrentDistrictId = "";
        }
        districtWheel.setPadding(padding);
    }

    /**
     * 根据当前的省,更新市WheelView的信息
     */
    private void updateCities() {
        int pCurrent = mViewProvince.getCurrentItem();
        mCurrentProviceId = mProvinceDatas.get(pCurrent).getProvinceId();
        List cities = mCitisDatasMap.get(mCurrentProviceId);
        if (cities == null) {
            cities = new ArrayList<>();
        }

        CityWheelAdapter cityWheel = new CityWheelAdapter(context, cities);
        // 设置可见条目数量
        cityWheel.setTextColor(textColor);
        cityWheel.setTextSize(textSize);
        mViewCity.setViewAdapter(cityWheel);
        mViewCity.setCurrentItem(0);
        cityWheel.setPadding(padding);
        updateAreas();
    }

    @Override
    public void setType(int type) {
    }

    @Override
    public void show() {
        if (!isShow()) {
            setUpData();
            popwindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);
        }
    }

    @Override
    public void hide() {
        if (isShow()) {
            popwindow.dismiss();
        }
    }

    @Override
    public boolean isShow() {
        return popwindow.isShowing();
    }

    @Override
    public void onChanged(WheelView wheel, int oldValue, int newValue) {
        if (wheel == mViewProvince) {
            updateCities();
        } else if (wheel == mViewCity) {
            updateAreas();
        } else if (wheel == mViewDistrict) {
            mCurrentDistrictId = mDistrictDatasMap.get(mCurrentCityId).get(newValue).getAreaId();
        }
    }
}

布局文件pop_my_citypicker.xml



    

        

            

            

            

        

        

            

            

            

            

            

            
        
    

省市区三级数据封装

//省
public class ProvinceList implements Serializable {
    private String provinceId;
    private String provinceName;
    List cityList;

    public List getCityList() {
        return this.cityList;
    }

    public void setCityList(List cityList) {
        this.cityList = cityList;
    }

    public String getProvinceId() {
        return this.provinceId;
    }

    public void setProvinceId(String provinceId) {
        this.provinceId = provinceId;
    }

    public String getProvinceName() {
        return this.provinceName;
    }

    public void setProvinceName(String provinceName) {
        this.provinceName = provinceName;
    }
}
//市
public class CityList implements Serializable {
    private String cityId;
    private String cityName;
    private List areaList;

    public CityList() {
    }

    public String getCityId() {
        return this.cityId;
    }

    public void setCityId(String cityId) {
        this.cityId = cityId;
    }

    public String getCityName() {
        return this.cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public List getAreaList() {
        return this.areaList;
    }

    public void setAreaList(List areaList) {
        this.areaList = areaList;
    }
}
//区
public class AreaList implements Serializable {
    private String areaId;
    private String areaName;

    public AreaList() {
    }

    public String getAreaId() {
        return this.areaId;
    }

    public void setAreaId(String areaId) {
        this.areaId = areaId;
    }

    public String getAreaName() {
        return this.areaName;
    }

    public void setAreaName(String areaName) {
        this.areaName = areaName;
    }
}

上述内容其实很简单,就不多做赘述,接下来就是需要我们在做一个点击事件之后所进行的操作,首先需要定义我们所需要的省市区三级列表缓存

    /**
     * 所有省
     */
    protected List mProvinceDatas;

    /**
     * key - 省 value - 市
     */
    protected Map> mCitisDatasMap = new HashMap<>();

    /**
     * key - 市 values - 区
     */
    protected Map> mDistrictDatasMap = new HashMap<>();

    choooseAddress.setOnClickListener(v -> {
          requestArea();//所在区域选择
    });

然后需要进行的操作就是在接口调用成功之后将我们所需要的省市区三级数据放入我们之前定义的HashMap当中

if (resp.getData() != null && resp.getData().size() > 0) {
  mProvinceDatas = resp.getData();
  mCitisDatasMap = new HashMap<>();
  mDistrictDatasMap = new HashMap<>();
  for (AreasResponseParam param1 : resp.getData()) {
       if (param1.getCityList() != null && param1.getCityList().size() > 0) {
             mCitisDatasMap.put(param1.getProvinceId(), param1.getCityList());
                 for (CityListResponseParam param2 : param1.getCityList()) {
                         if (param2.getAreaList() != null && param2.getAreaList().size() > 0) {
                             mDistrictDatasMap.put(param2.getCityId(), param2.getAreaList());
                         }
                   }
             }
        }
   chooseArea(schoolAddress);
}

这里进行的是我们对于所在的文本区域进行点击事件之后的操作

    //TextView的点击事件
    public void chooseArea(View view) {
        selectAddress();//调用CityPicker选取区域
    }

最后一步,调用我们自定义的CityPicker,然后获取省市区的ID并对于文本区域进行setText进行文本显示

    @SuppressLint("SetTextI18n")
    private void selectAddress() {
        MyCityPicker cityPicker = new MyCityPicker.Builder(SetSchoolNameActivity.this)
                .textSize(14)
                .title("地址选择")
                .titleBackgroundColor("#FFFFFF")
                .confirTextColor("#F1C764")
                .cancelTextColor("#999999")
                .textColor(Color.parseColor("#000000"))
                .provinceCyclic(false)
                .cityCyclic(false)
                .districtCyclic(false)
                .visibleItemsCount(7)
                .itemPadding(10)
                .onlyShowProvinceAndCity(false)
                .build();
        cityPicker.setmProvinceDatas(mProvinceDatas);
        cityPicker.setmCitisDatasMap(mCitisDatasMap);
        cityPicker.setmDistrictDatasMap(mDistrictDatasMap);
        cityPicker.show();
        //监听方法,获取选择结果
        cityPicker.setOnCityItemClickListener(citySelected -> {
            //获取省市区三级的城市ID
            provinceId = mProvinceDatas.get(citySelected[0]).getProvinceId();
            cityId = mProvinceDatas.get(citySelected[0]).getCityList().get(citySelected[1]).getCityId();
            areaId = mProvinceDatas.get(citySelected[0]).getCityList().get(citySelected[1]).getAreaList().get(citySelected[2]).getAreaId();
            //对于我们所进行的文本区域进行set所选择的省市区的值
            schoolAddress.setText(mProvinceDatas.get(citySelected[0]).getProvinceName() +
                    mProvinceDatas.get(citySelected[0]).getCityList().get(citySelected[1]).getCityName() +
                    mProvinceDatas.get(citySelected[0]).getCityList().get(citySelected[1]).getAreaList().get(citySelected[2]).getAreaName());
        });
    }

附上省市区三级自定义的adapter

public class ProvinceWheelAdapter extends AbstractWheelTextAdapter {
    /**
     * Constructor
     *
     * @param context the current context
     * @param items   the items
     */
    // items
    private List items;

    public ProvinceWheelAdapter(Context context, List items) {
        super(context);
        //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE);
        this.items = items;
    }

    @Override
    public CharSequence getItemText(int index) {
        if (index >= 0 && index < items.size()) {
            return items.get(index).getProvinceName();
        }
        return null;
    }

    @Override
    public int getItemsCount() {
        return items.size();
    }
}
public class CityWheelAdapter extends AbstractWheelTextAdapter {
    /**
     * Constructor
     *
     * @param context the current context
     * @param items   the items
     */
    // items
    private List items;

    public CityWheelAdapter(Context context, List items) {
        super(context);
        //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE);
        this.items = items;
    }

    @Override
    public CharSequence getItemText(int index) {
        if (index >= 0 && index < items.size()) {
            return items.get(index).getCityName();
        }
        return null;
    }

    @Override
    public int getItemsCount() {
        return items.size();
    }
}
public class AreaWheelAdapter extends AbstractWheelTextAdapter {
    /**
     * Constructor
     *
     * @param context the current context
     * @param items   the items
     */
    // items
    private List items;

    public AreaWheelAdapter(Context context, List items) {
        super(context);
        //setEmptyItemResource(TEXT_VIEW_ITEM_RESOURCE);
        this.items = items;
    }

    @Override
    public CharSequence getItemText(int index) {
        if (index >= 0 && index < items.size()) {
            return items.get(index).getAreaName();
        }
        return null;
    }

    @Override
    public int getItemsCount() {
        return items.size();
    }
}
最终结果展示

代码传送门

你可能感兴趣的:(自定义三级联动列表选择省市区)