Android地址选择器的实现

作者: 龙旋之谷 | 来源:发表于2019-05-13 00:32 被阅读16次

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

    1.先看实现的效果图


    QQ截图20190512221706.png

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

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

    
    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进行地址选择

    /**
         * 设置弹出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.设置选择器默认数据

     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.将获取的省市区的数据进行分类

      /**
         * 获取省的数据
         *
         * @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.设置地址选择器的布局文件

    <?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的童鞋可以在公众号回复 “地址选择器”


    以下是个人公众号(longxuanzhigu),之后发布的文章会同步到该公众号,方便交流学习Android知识及分享个人爱好文章:


    公众号.jpg

    相关文章

      网友评论

        本文标题:Android地址选择器的实现

        本文链接:https://www.haomeiwen.com/subject/fqlkaqtx.html