Android仿京东实现地址选择功能

龙旋

共 24505字,需浏览 50分钟

 ·

2021-03-07 08:47

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

实现流程:

    1、效果图

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

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

    4、设置选择器默认数据

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

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

    7、总结


实现步骤:

1、效果图


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


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的外层layoutprivate 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);        }elsethrow 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;    }@Overridepublic 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);        }@Overridepublic void setText(CharSequence text, BufferType type) {if(isSelected)                setTextColor(TextSelectedColor);else                setTextColor(TextEmptyColor);super.setText(text, type);        }@Overridepublic 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>{@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {            MyViewHolder viewHolder =new MyViewHolder(LayoutInflater.from(mContext).inflate(                            R.layout.item_address,parent,false));return viewHolder;        }@Overridepublic 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() {@Overridepublic 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);                        }                    }                }            });        }@Overridepublic 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>


7、总结


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


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


到这里就结束啦


点击这里留言交流哦


浏览 115
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报