前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android地址选择器的实现

Android地址选择器的实现

作者头像
SoullessCoder
修改2021-02-03 10:07:23
4K1
修改2021-02-03 10:07:23
举报
文章被收录于专栏:CodeCode

最近在做地址管理的功能,新建地址的时候,需要根据后台提供的省市区的数据,让用户进行地址的选择,最近项目比较赶,本来想网上找一个的,可是找了很久都没找到我想要的效果,所以就根据后台提供的数据,弄了一个。

1.先看实现的效果图

QQ截图20190512221706.png

本来数据是根据请求后台接口返回的数据,我这里就不请求后台数据了,直接把请求成功后的数据写死,可是把全国省市区的数据太多,导致报错:字符串数据太长,所以我这里只获取了北京的数据。

2.自定义收货地址选择器

代码语言:txt
复制
public class AddressSelector extends LinearLayout implements View.OnClickListener{
    private int TextSelectedColor = Color.parseColor("#D5A872");
    private int TextEmptyColor = Color.parseColor("#333333");
    //顶部的tab集合
    private ArrayList<Tab> tabs;
    //列表的适配器
    private AddressAdapter addressAdapter;
    private ArrayList<CityInterface> cities;
    private OnItemClickListener onItemClickListener;
    private OnTabSelectedListener onTabSelectedListener;
    private RecyclerView list;
    //tabs的外层layout
    private LinearLayout tabs_layout;
    //会移动的横线布局
    private Line line;
    private Context mContext;
    //总共tab的数量
    private int tabAmount = 3;
    //当前tab的位置
    private int tabIndex = 0;
    //分隔线
    private View grayLine;
    //列表文字大小
    private int listTextSize = -1;
    //列表文字颜色
    private int listTextNormalColor = Color.parseColor("#333333");
    //列表文字选中的颜色
    private int listTextSelectedColor = Color.parseColor("#D5A872");
    //列表icon资源
    private int listItemIcon = -1;
    public AddressSelector(Context context) {
        super(context);
        init(context);
    }

    public AddressSelector(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public AddressSelector(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    private void init(Context context){
        removeAllViews();
        this.mContext = context;
        setOrientation(VERTICAL);
        tabs_layout = new LinearLayout(mContext);
        tabs_layout.setWeightSum(tabAmount);
        tabs_layout.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.WRAP_CONTENT));
        tabs_layout.setOrientation(HORIZONTAL);
        addView(tabs_layout);
        tabs = new ArrayList<>();
        Tab tab = newTab("请选择",true);
        tabs_layout.addView(tab);
        tabs.add(tab);
        for(int i = 1;i<tabAmount;i++){
            Tab _tab = newTab("",false);
            _tab.setIndex(i);
            tabs_layout.addView(_tab);
            tabs.add(_tab);
        }
        line = new Line(mContext);
        line.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,6));
        line.setSum(tabAmount);
        addView(line);
        grayLine = new View(mContext);
        grayLine.setLayoutParams(new LayoutParams(
                LayoutParams.MATCH_PARENT,2));
        grayLine.setBackgroundColor(mContext.getResources().getColor(R.color.line_DDDDDD));
        addView(grayLine);
        list = new RecyclerView(mContext);
        list.setLayoutParams(new ViewGroup.LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        list.setLayoutManager(new LinearLayoutManager(mContext));
        addView(list);
    }
    /**
     * 得到一个新的tab对象
     * */
    private Tab newTab(CharSequence text, boolean isSelected){
        Tab tab = new Tab(mContext);
        tab.setLayoutParams(new LayoutParams(0,LayoutParams.WRAP_CONTENT,1));
        tab.setGravity(Gravity.CENTER);
        tab.setPadding(0,5,0,5);
        tab.setSelected(isSelected);
        tab.setText(text);
        tab.setTextEmptyColor(TextEmptyColor);
        tab.setTextSelectedColor(TextSelectedColor);
        tab.setOnClickListener(this);
        return tab;
    }
    /**
     * 设置tab的数量,默认3个,不小于2个
     * @param tabAmount tab的数量
     * */
    public void setTabAmount(int tabAmount) {
        if(tabAmount >= 2){
            this.tabAmount = tabAmount;
            init(mContext);
        }
        else
            throw new RuntimeException("AddressSelector tabAmount can not less-than 2 !");
    }
    /**
     * 设置列表的点击事件回调接口
     * */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }
    /**
     * 设置列表的数据源,设置后立即生效
     * */
    public void setCities(ArrayList cities) {
        if(cities == null||cities.size() <= 0)
            return;
        if(cities.get(0) instanceof CityInterface){
            this.cities = cities;
            if(addressAdapter == null){
                addressAdapter = new AddressAdapter();
                list.setAdapter(addressAdapter);
            }
            addressAdapter.notifyDataSetChanged();
        }else{
            throw new RuntimeException("AddressSelector cities must implements CityInterface");
        }
    }
    /**
     * 设置顶部tab的点击事件回调
     * */
    public void setOnTabSelectedListener(OnTabSelectedListener onTabSelectedListener) {
        this.onTabSelectedListener = onTabSelectedListener;
    }

    @Override
    public void onClick(View v) {
        Tab tab = (Tab) v;
        //如果点击的tab大于index则直接跳出
        if(tab.index > tabIndex)
            return;
        tabIndex = tab.index;
        if(onTabSelectedListener != null){
            if(tab.isSelected)
                onTabSelectedListener.onTabReselected(AddressSelector.this,tab);
            else
                onTabSelectedListener.onTabSelected(AddressSelector.this,tab);
        }
        resetAllTabs(tabIndex);
        line.setIndex(tabIndex);
        tab.setSelected(true);
    }

    private void resetAllTabs(int tabIndex){
        if(tabs != null)
        for(int i =0;i<tabs.size();i++){
            tabs.get(i).resetState();
            if(i > tabIndex){
                tabs.get(i).setText("");
            }
        }
    }
    /**
     * 设置Tab文字选中的颜色
     * */
    public void setTextSelectedColor(int textSelectedColor) {
        TextSelectedColor = textSelectedColor;
    }
    /**
     * 设置Tab文字默认颜色
     * */
    public void setTextEmptyColor(int textEmptyColor) {
        TextEmptyColor = textEmptyColor;
    }
    /**
     * 设置Tab横线的颜色
     * */
    public void setLineColor(int lineColor) {
        line.setSelectedColor(lineColor);
    }
    /**
     * 设置tab下方分隔线的颜色
     * */
    public void setGrayLineColor(int grayLineColor) {
        grayLine.setBackgroundColor(grayLineColor);
    }
    /**
     * 设置列表文字大小
     * */
    public void setListTextSize(int listTextSize) {
        this.listTextSize = listTextSize;
    }
    /**
     * 设置列表文字颜色
     * */
    public void setListTextNormalColor(int listTextNormalColor) {
        this.listTextNormalColor = listTextNormalColor;
    }
    /**
     * 设置列表选中文字颜色
     * */
    public void setListTextSelectedColor(int listTextSelectedColor) {
        this.listTextSelectedColor = listTextSelectedColor;
    }
    /**
     * 设置列表icon资源
     * */
    public void setListItemIcon(int listItemIcon) {
        this.listItemIcon = listItemIcon;
    }

    /**
     * 标签控件
     * */
    @SuppressLint("AppCompatCustomView")
    public class Tab extends TextView {
        private int index = 0;
        private int TextSelectedColor = Color.parseColor("#D5A872");
        private int TextEmptyColor = Color.parseColor("#333333");
        /**
         * 是否选中状态
         * */
        private boolean isSelected = false;
        public Tab(Context context) {
            super(context);
            init();
        }

        public Tab(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }

        public Tab(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
        private void init(){
            setTextSize(15);
        }
        @Override
        public void setText(CharSequence text, BufferType type) {
            if(isSelected)
                setTextColor(TextSelectedColor);
            else
                setTextColor(TextEmptyColor);
            super.setText(text, type);
        }

        @Override
        public void setSelected(boolean selected) {
            isSelected = selected;
            setText(getText());
        }

        public int getIndex() {
            return index;
        }

        public void setIndex(int index) {
            this.index = index;
        }
        public void resetState(){
            isSelected = false;
            setText(getText());
        }

        public void setTextSelectedColor(int textSelectedColor) {
            TextSelectedColor = textSelectedColor;
        }

        public void setTextEmptyColor(int textEmptyColor) {
            TextEmptyColor = textEmptyColor;
        }
    }
    /**
     * 横线控件
     * */
    private class Line extends LinearLayout {
        private int sum = 3;
        private int oldIndex = 0;
        private int nowIndex = 0;
        private View indicator;
        private int SelectedColor = Color.parseColor("#D5A872");
        public Line(Context context) {
            super(context);
            init(context);
        }

        public Line(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }

        public Line(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context);
        }
        private void init(Context context){
            setOrientation(HORIZONTAL);
            setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT,6));
            setWeightSum(tabAmount);
            indicator= new View(context);
            indicator.setLayoutParams(new LayoutParams(0,LayoutParams.MATCH_PARENT,1));
            indicator.setBackgroundColor(SelectedColor);
            addView(indicator);
        }
        public void setIndex(int index){
            int onceWidth = getWidth()/sum;
            this.nowIndex = index;
            ObjectAnimator animator = ObjectAnimator.ofFloat(indicator, "translationX", indicator.getTranslationX(), (nowIndex-oldIndex)*onceWidth);
            animator.setDuration(300);
            animator.start();
        }

        public void setSum(int sum) {
            this.sum = sum;
        }

        public void setSelectedColor(int selectedColor) {
            SelectedColor = selectedColor;
        }
    }
    private class AddressAdapter extends RecyclerView.Adapter<AddressAdapter.MyViewHolder>{
        @Override
        public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            MyViewHolder viewHolder =
                    new MyViewHolder(LayoutInflater.from(mContext).inflate(
                            R.layout.item_address,parent,false));
            return viewHolder;
        }

        @Override
        public void onBindViewHolder(MyViewHolder holder, final int position) {
            if(listItemIcon != -1)
                holder.img.setImageResource(listItemIcon);
            if(listTextSize != -1)
                holder.tv.setTextSize(listTextSize);
            if(TextUtils.equals(tabs.get(tabIndex).getText(),cities.get(position).getCityName())){
                holder.img.setVisibility(View.VISIBLE);
                holder.tv.setTextColor(listTextSelectedColor);
            }else{
                holder.img.setVisibility(View.INVISIBLE);
                holder.tv.setTextColor(listTextNormalColor);
            }
            holder.tv.setText(cities.get(position).getCityName());
            holder.itemView.setTag(cities.get(position));
            holder.itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(onItemClickListener != null){
                        onItemClickListener.itemClick(AddressSelector.this,(CityInterface) v.getTag(),tabIndex,position);
                        tabs.get(tabIndex).setText(((CityInterface) v.getTag()).getCityName());
                        tabs.get(tabIndex).setTag(v.getTag());
                        if(tabIndex+1 < tabs.size()){
                            tabIndex ++;
                            resetAllTabs(tabIndex);
                            line.setIndex(tabIndex);
                            tabs.get(tabIndex).setText("请选择");
                            tabs.get(tabIndex).setSelected(true);
                        }
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return cities.size();
        }
        class MyViewHolder extends RecyclerView.ViewHolder{
            public TextView tv;
            public ImageView img;
            public View itemView;
            public MyViewHolder(View itemView) {
                super(itemView);
                this.itemView = itemView;
                tv = (TextView) itemView.findViewById(R.id.item_address_tv);
                img = (ImageView) itemView.findViewById(R.id.item_address_img);
            }
        }
    }
    public interface OnTabSelectedListener {
        void onTabSelected(AddressSelector addressSelector, Tab tab);
        void onTabReselected(AddressSelector addressSelector, Tab tab);
    }
}

3.Demo中设置点击按钮打开PopWindow进行地址选择

代码语言:txt
复制
/**
     * 设置弹出PopWindow
     * @param v
     */
    private void setAddressSelectorPopup(View v) {
        int screenHeigh = getResources().getDisplayMetrics().heightPixels;

        CommonPopWindow.newBuilder()
                .setView(R.layout.pop_address_selector_bottom)
                .setAnimationStyle(R.style.AnimUp)
                .setBackgroundDrawable(new BitmapDrawable())
                .setSize(ViewGroup.LayoutParams.MATCH_PARENT, Math.round(screenHeigh * 0.6f))
                .setViewOnClickListener(this)
                .setBackgroundDarkEnable(true)
                .setBackgroundAlpha(0.7f)
                .setBackgroundDrawable(new ColorDrawable(999999))
                .build(this)
                .showAsBottom(v);
    }

    @Override
    public void getChildView(final PopupWindow mPopupWindow, View view, int mLayoutResId) {
        switch (mLayoutResId) {
            case R.layout.pop_address_selector_bottom:
                ImageView imageBtn = view.findViewById(R.id.img_guanbi);
                AddressSelector addressSelector = view.findViewById(R.id.address);

                //数据解析
                AddressSelectorReq addressSelectorReq = new Gson().fromJson(String.valueOf(response), AddressSelectorReq.class);
                //设置默认选择数据
                dealWithAddressSelector(addressSelector, addressSelectorReq.getDatas(), mPopupWindow);

                imageBtn.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mPopupWindow.dismiss();
                    }
                });
                break;
        }
    }

4.设置选择器默认数据

代码语言:txt
复制
 private void dealWithAddressSelector(AddressSelector addressSelector, final List<AddressSelectorReq.DatasBean> 
            addressSelectorList, final PopupWindow mPopupWindow) {
        final String[] sheng = new String[3];

        final ArrayList<ItemAddressReq> itemAddressReqs = getItemAddressSheng(addressSelectorList);
        addressSelector.setTabAmount(3);
        //设置数据
        addressSelector.setCities(itemAddressReqs);
        //设置Tab横线的颜色
        addressSelector.setLineColor(Color.parseColor("#D5A872"));
        //设置Tab文字默认颜色
        addressSelector.setTextEmptyColor(Color.parseColor("#000000"));
        //设置列表选中文字颜色
        addressSelector.setListTextSelectedColor(Color.parseColor("#D5A872"));
        //设置Tab文字选中的颜色
        addressSelector.setTextSelectedColor(Color.parseColor("#D5A872"));

        //设置列表的点击事件回调接口
        addressSelector.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void itemClick(AddressSelector addressSelector, CityInterface city, int tabPosition, int selecePos) {
                switch (tabPosition) {
                    case 0:
                        //设置省列表数据
                        sheng[0] = city.getCityName();
                        saveId[0] = addressSelectorList.get(selecePos).getDb_id();
                        childrenBeanXList = addressSelectorList.get(selecePos).getDb_children();
                        addressSelector.setCities(getItemAddressShi(childrenBeanXList));
                        break;
                    case 1:
                        //设置市列表数据
                        sheng[1] = city.getCityName();
                        saveId[1] = childrenBeanXList.get(selecePos).getCb_id();
                        childrenBeans = childrenBeanXList.get(selecePos).getCb_children();
                        addressSelector.setCities(getItemAddressQu(childrenBeans));
                        break;
                    case 2:
                        //设置区列表数据
                        sheng[2] = city.getCityName();
                        saveId[2] = childrenBeans.get(selecePos).getId();
                        text_suozaidiqu.setText(sheng[0] + sheng[1] + sheng[2]);
                        mPopupWindow.dismiss();
                        break;
                }
            }
        });


        //设置顶部tab的点击事件回调
        addressSelector.setOnTabSelectedListener(new AddressSelector.OnTabSelectedListener() {
            @Override
            public void onTabSelected(AddressSelector addressSelector, AddressSelector.Tab tab) {
                switch (tab.getIndex()) {
                    case 0:
                        addressSelector.setCities(itemAddressReqs);
                        break;
                    case 1:
                        addressSelector.setCities(getItemAddressShi(childrenBeanXList));
                        break;
                    case 2:
                        addressSelector.setCities(getItemAddressQu(childrenBeans));
                        break;
                }
            }

            @Override
            public void onTabReselected(AddressSelector addressSelector, AddressSelector.Tab tab) {

            }
        });
    }

5.将获取的省市区的数据进行分类

代码语言:txt
复制
  /**
     * 获取省的数据
     *
     * @param addressSelectorList
     * @return
     */
    @NonNull
    private ArrayList<ItemAddressReq> getItemAddressSheng(List<AddressSelectorReq.DatasBean> addressSelectorList) {
        final ArrayList<ItemAddressReq> itemAddressReqs = new ArrayList<>();
        for (int i = 0; i < addressSelectorList.size(); i++) {
            ItemAddressReq itemAddressReq = new ItemAddressReq();
            itemAddressReq.setAreaAbbName(addressSelectorList.get(i).getDb_areaAbbName());
            itemAddressReq.setAreaCode(addressSelectorList.get(i).getDb_areaCode());
            itemAddressReq.setAreaEnName(addressSelectorList.get(i).getDb_areaEnName());
            itemAddressReq.setAreaType(addressSelectorList.get(i).getDb_areaType());
            itemAddressReq.setAreaZip(addressSelectorList.get(i).getDb_areaZip());
            itemAddressReq.setAreaName(addressSelectorList.get(i).getDb_areaName());
            itemAddressReq.setId(addressSelectorList.get(i).getDb_id());
            itemAddressReq.setParentId(addressSelectorList.get(i).getDb_parentId());
            itemAddressReqs.add(itemAddressReq);
        }
        return itemAddressReqs;
    }


    /**
     * 获取市的数据
     *
     * @return
     */
    @NonNull
    private ArrayList<ItemAddressReq> getItemAddressShi(List<AddressSelectorReq.DatasBean.ChildrenBeanX> datas) {
        final ArrayList<ItemAddressReq> itemAddressReqs = new ArrayList<>();
        for (int i = 0; i < datas.size(); i++) {
            ItemAddressReq itemAddressReq = new ItemAddressReq();
            itemAddressReq.setAreaAbbName(datas.get(i).getCb_areaAbbName());
            itemAddressReq.setAreaCode(datas.get(i).getCb_areaCode());
            itemAddressReq.setAreaEnName(datas.get(i).getCb_areaEnName());
            itemAddressReq.setAreaType(datas.get(i).getCb_areaType());
            itemAddressReq.setAreaZip(datas.get(i).getCb_areaZip());
            itemAddressReq.setAreaName(datas.get(i).getCb_areaName());
            itemAddressReq.setId(datas.get(i).getCb_id());
            itemAddressReq.setParentId(datas.get(i).getCb_parentId());
            itemAddressReqs.add(itemAddressReq);
        }
        return itemAddressReqs;
    }

    /**
     * 获取区的数据
     *
     * @param addressSelectorList
     * @return
     */
    @NonNull
    private ArrayList<ItemAddressReq> getItemAddressQu(List<AddressSelectorReq.DatasBean.ChildrenBeanX.ChildrenBean> addressSelectorList) {
        final ArrayList<ItemAddressReq> itemAddressReqs = new ArrayList<>();
        for (int i = 0; i < addressSelectorList.size(); i++) {
            ItemAddressReq itemAddressReq = new ItemAddressReq();
            itemAddressReq.setAreaAbbName(addressSelectorList.get(i).getAreaAbbName());
            itemAddressReq.setAreaCode(addressSelectorList.get(i).getAreaCode());
            itemAddressReq.setAreaEnName(addressSelectorList.get(i).getAreaEnName());
            itemAddressReq.setAreaType(addressSelectorList.get(i).getAreaType());
            itemAddressReq.setAreaZip(addressSelectorList.get(i).getAreaZip());
            itemAddressReq.setAreaName(addressSelectorList.get(i).getAreaName());
            itemAddressReq.setId(addressSelectorList.get(i).getId());
            itemAddressReq.setParentId(addressSelectorList.get(i).getParentId());
            itemAddressReqs.add(itemAddressReq);
        }
        return itemAddressReqs;
    }

6.设置地址选择器的布局文件

代码语言:txt
复制
<?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:layout_alignParentBottom="true"
    android:background="#fff"
    android:orientation="vertical"
    android:padding="1dp">

    <ImageView
        android:id="@+id/img_guanbi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginTop="15dp"
        android:layout_marginRight="15dp"
        android:src="@drawable/guanbi" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:text="所在区域"
        android:textColor="#777777"
        android:textSize="16sp" />

    <com.showly.ylin.addressselectdemo.addressselector.AddressSelector
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="70dp" />
</RelativeLayout>

6.总结

到这里就实现了地址选择器的功能,因为后台提供的地址数据可能不一样,所以这里就不把全部数据拿出来了,需要完整数据的也可以Q我。

需要Demo的童鞋可以在公众号回复 “地址选择器”


小编整理了一份Android电子书籍,需要的童鞋关注公众号回复:"e_books" 即可获取哦!

在这里插入图片描述
在这里插入图片描述

欢迎关注公众号(longxuanzhigu),获得更多福利、精彩内容哦!

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.05.13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档