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

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);elseonTabSelectedListener.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);elsesetTextColor(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);}@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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;}}@Overridepublic void onTabReselected(AddressSelector addressSelector, AddressSelector.Tab tab) {}});}

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

  /*** 获取省的数据** @param addressSelectorList* @return*/@NonNullprivate 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*/@NonNullprivate 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*/@NonNullprivate 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"><ImageViewandroid: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" /><TextViewandroid: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.AddressSelectorandroid:id="@+id/address"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="70dp" />
</RelativeLayout>

6.总结
到这里就实现了地址选择器的功能,因为后台提供的地址数据可能不一样,所以这里就不把全部数据拿出来了,需要完整数据的也可以Q我。
需要Demo的童鞋可以在公众号回复 “地址选择器”


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

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

Android地址选择器的实现相关推荐

  1. android开发地址选择器,Android地址选择器 类似于京东的地址选择

    简介 最近东西写的挺多的,这不又要弄一个类似于京东的地址选择器,然后刚开始我是不愿意自己去写的,这东西真的是浪费时间.但是下班后回到家找了一圈没找到一个合适的,好吧,那我就自己来封装一个呗,反正生命在 ...

  2. android 地址选择器_48种Android开发的开源库汇总

    一.安全 1.SQLCipher Sqlite加密工具 项目地址: https://github.com/sqlcipher/sqlcipher 帮助文档: http://sqlcipher.net/ ...

  3. Android进阶之路 - 仿京东地址选择器使用指南

    因为现在项目的地址选择器比较low,自己又比较懒,所以就找到了仿京东的地址选择器,观赏几篇博文之后,发现总是被半路卡死,很难一路走到底,所以在github找到了项目地址,但是作者的功能简介又介绍的不是 ...

  4. Android 选择器 PickerView实例,时间选择器、地址选择器、单项选择器、多项选择器自定义布局

    是采用的github开源库PickerView,省时省力.最终效果图见最后 首先添加依赖: //PickerView 选择器 implementation 'com.contrarywind:Andr ...

  5. Android进阶之路 - Citypicker 五分钟内快速实现地址选择器

    从早期的时候就比较喜欢拉框架直接用,所以以前记录了很多 关于 CityPicker 框架,我用的时候还是2017年,但是这几年(2022)改变了很多,扩展性也很强,如果要了解最新使用的话,最好还是去 ...

  6. android双日期选择器,AndroidPicker 安卓选择器类库,包括日期选择器、时间选择器、单项选择器、双项选择器、城市地址选择器、车牌号选择器 @codeKK Android开源站...

    安卓选择器类库,包括日期及时间选择器(可设置范围).单项选择器(可用于性别.职业.学历.星座等).城市地址选择器(分省级.地级及县级).数字选择器(可用于年龄.身高.体重.温度等).双项选择器.颜色选 ...

  7. android 京东地址,MUI仿京东App地址选择器

    才学JS不久,刚好项目需要一个京东地址选择器,所以尝试着写了一个,dom获取较为复杂,纯粹使用自己了解到的东西 依赖 //css是用rem写的 //mui提供的城市js HTML 请选择 请选择 请选 ...

  8. android 仿照ios 图片选择,GitHub - wildma/PictureSelector: Android 图片选择器(仿 IOS 图片选择控件)...

    PictureSelector Android 图片选择器(仿 IOS 图片选择控件) 效果图 功能特点 支持通过拍照获取图片 支持通过相册获取图片 支持图片是否裁剪两种场景 支持仿 IOS 底部弹出 ...

  9. 使用Android-PickerView实现地址选择器时间选择器

    这里贡献下我使用Android-PickerView实现地址选择器遇到的坑,算是一个笔记.首先要吐槽下后台接口,为了实现移动端和web端的统一(ps:可能他没搞过后台接口),修改地址的时候本来要用下拉 ...

最新文章

  1. 安全性断言标记语言(SAML)介绍
  2. 转 关于 D3D的 SetRenderState 以及AlphaBlend 和AlphaTest
  3. 已解决AttributeError set object has no attribute items(亲测)
  4. 服务器3个w目录文件夹,第 4 章 目录服务器条目 (Sun Java System Directory Server Enterprise Edition 6.2 管理指南)...
  5. 解决:Cannot read property ‘component‘ of undefined ( 即 vue-router 0.x 转化为 2.x)
  6. MySQL/sqlserver查询in操作 查询结果按in集合顺序显示
  7. iOS 怎么设置 UITabBarController 的第n个item为第一响应者?
  8. 小技巧 ----- 通过二进制串的位运算进行二维指数型枚举
  9. Linux服务器开机自动启动服务或脚本的方法
  10. MCE公司:新型 RORγt 小分子反向激动剂的发现
  11. 2021年度最全“Java面试宝典+Java核心知识集”,一箭双雕杠春招
  12. 如何查询目标计算机的ip地址,基于Wireshark获取目标ip地址
  13. 【STM32】 JDY-31蓝牙模块
  14. Pr视频剪辑出现红线
  15. Input length must be multiple of 8 when decrypting with padded cipher 错误
  16. php ipa 版本定制,自建IOS企业包ipa包 下载服务
  17. python基础----Day05
  18. java手机怎么测网速_用来检查网络和网速android小程序
  19. 不一定是黑客,也可以是守护神《运用Python成为顶级黑客》
  20. Java Socket 如何接收byte和String

热门文章

  1. 微信小程序使用数字滚动动画
  2. locust实现压测
  3. 数据解读 | 广东省内,谁才有资格做下一个深圳?
  4. unity新粒子系统的碰撞和触发
  5. python百度地图和租房信息_python爬虫租房信息在地图上显示的方法
  6. 【日语学习】日语 N2 词汇核心动词 200 个
  7. 口红见缝插针小游戏的一些参数说明
  8. Java打印乘法口诀表(任何数)
  9. 密码应用安全性评估实施要点之二密码技术应用要求与实现要点(4)
  10. 理想汽车的2021,是否“理想”?