Android地址选择器的实现

2021-02-03 10:07:23 浏览数 (1)

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

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),获得更多福利、精彩内容哦!

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

0 人点赞