热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

Android实现四级联动地址选择器

这篇文章主要为大家详细介绍了Android实现四级联动地址选择器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android实现四级联动地址选择器的具体代码,供大家参考,具体内容如下

效果如下:

代码传送阵:

address_selector.xml



  

    

    

    

    

    

    

    

    
  

AddressDialog.java

public class AddressDialog extends DialogFragment {
  @BindView(R.id.textViewProvince)
  TextView textViewProvince;
  @BindView(R.id.textViewCity)
  TextView textViewCity;
  @BindView(R.id.textViewArea)
  TextView textViewArea;
  @BindView(R.id.textViewStreet)
  TextView textViewStreet;
  @BindView(R.id.iv_close)
  AppCompatImageView ivClose;
  @BindView(R.id.indicator)
  View indicator;
  @BindView(R.id.divider)
  View divider;
  @BindView(R.id.recycler_view)
  RecyclerView recyclerView;
  @BindView(R.id.cl_container)
  ConstraintLayout clContainer;
  @BindView(R.id.ll_container)
  LinearLayout llContainer;
  Unbinder unbinder;
  private CompositeDisposable compositeDisposable = new CompositeDisposable();
  private float measuredHeight = 0F;
  // 当前tab 0省1市2区
  private int currentTab = 0;
  // 省
  private ArrayList proviceList = new ArrayList<>();
  // 市
  private ArrayList cityList = new ArrayList<>();
  private ConcurrentHashMap> cityMap = new ConcurrentHashMap<>();
  // 区
  private ArrayList areaList = new ArrayList<>();
  private ConcurrentHashMap> areaMap = new ConcurrentHashMap<>();
  //街道
  private ArrayList streetList = new ArrayList<>();
  private ConcurrentHashMap> streetMap = new ConcurrentHashMap<>();

  private BaseQuickAdapter mAdapter;
  private OnSelectListener listener;
  private String textProvince = "";
  private String textCity = "";
  private String textArea = "";
  private String textStreet = "";
  private ProgressDialog mProgressDialog;
  @Nullable
  @Override
  public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.address_selector, container, false);
    unbinder = ButterKnife.bind(this, view);
    return view;
  }

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setStyle(STYLE_NO_TITLE, R.style.Style_Dialog_Transparent);
  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    textViewProvince.setSelected(true);
    float measureText = textViewProvince.getPaint().measureText("请选择");
    indicator.getLayoutParams().width = (int) measureText;
    LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)clContainer.getLayoutParams();
    layoutParams.topMargin = listener.getHeight() == 0 &#63; UIUtil.dip2px(MyApplication.applicationContext,180f) :listener.getHeight();
    clContainer.setLayoutParams(layoutParams);
    initData();
    initClick();

    ViewUtils.postMeasured(clContainer, new Runnable() {
      @Override
      public void run() {
        llContainer.animate().alpha(1f).setDuration(150).start();

        float measuredHeight = (float)clContainer.getMeasuredHeight();
        ObjectAnimator translatiOnY= ObjectAnimator.ofFloat(clContainer, "translationY", measuredHeight, 0f);
        translationY.setDuration(150);
        translationY.setInterpolator(new LinearInterpolator());
        translationY.start();
      }
    });

  }

  private void initData() {
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    mAdapter=new BaseQuickAdapter(R.layout.item_area) {
      @Override
      protected void convert(@NonNull BaseViewHolder helper, final County item) {
        helper.setText(R.id.textView,item.name);
        helper.getConvertView().setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            switch (currentTab) {
              case 0:
                getCityList(new Consumer>() {
                  @Override
                  public void accept(ArrayList counties) throws Exception {
                    // 本地是否存在
                    if (cityMap.containsKey(item.code)){
                      ArrayList list = cityMap.get(item.code);
                      if (list==null) {
                        list=new ArrayList<>();
                      }
                      notifyAdapter(list);
                    }else {
                      for (County next : cityList) {
                        if (cityMap.containsKey(item.code) && item.code.equals(next.provinceCode)) {
                          ArrayList list = cityMap.get(item.code);
                          if (list != null) {
                            list.add(next);
                            cityMap.put(next.provinceCode, list);
                          }
                        } else {
                          @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
                          ArrayList listCounty = new ArrayList<>();
                          listCounty.add(next);
                          cityMap.put(next.provinceCode, listCounty);
                        }
                      }
                    }
                    ArrayList list = cityMap.get(item.code);
                    notifyAdapter(list);
                  }
                });
                break;
              case 1:
                getAreaList(new Consumer>() {
                  @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
                  @Override
                  public void accept(ArrayList list) throws Exception {
                    if (areaMap.containsKey(item.code)) {
                      ArrayList arrayList = areaMap.get(item.code);
                      if (arrayList==null) {
                        arrayList =new ArrayList<>();
                      }
                      notifyAdapter(arrayList);
                    }else {
                      for (County county : areaList) {
                        if (areaMap.containsKey(item.code) && item.code.equals(county.cityCode)) {
                          ArrayList countyArrayList = areaMap.get(item.code);
                          if (countyArrayList != null) {
                            countyArrayList.add(county);
                            areaMap.put(county.code, countyArrayList);
                          }
                        }else {
                          ArrayList arrayList = new ArrayList<>();
                          arrayList.add(county);
                          areaMap.put(county.cityCode,arrayList);
                        }
                      }
                    }
                    ArrayList arrayList = areaMap.get(item.code);
                    notifyAdapter(arrayList);
                  }
                });
                break;
              case 2:

                if (mProgressDialog == null) {
                  mProgressDialog = new ProgressDialog(getActivity());
                }

                mProgressDialog.setCanceledOnTouchOutside(false);
                mProgressDialog.setCancelable(true);
                mProgressDialog.show();

                getStreetList(new Consumer>() {
                  @Override
                  public void accept(ArrayList list) throws Exception {

                    if (streetMap.containsKey(item.code)) {
                      ArrayList arrayList = streetMap.get(item.code);
                      if (arrayList==null) {
                        arrayList =new ArrayList<>();
                      }
                      notifyAdapter(arrayList);
                    }else {
                      for (County county : streetList) {
                        if (streetMap.containsKey(item.code) && item.code.equals(county.areaCode)) {
                          ArrayList countyArrayList = streetMap.get(item.code);
                          if (countyArrayList != null) {
                            countyArrayList.add(county);
                            streetMap.put(county.code, countyArrayList);
                          }
                        }else {
                          ArrayList arrayList = new ArrayList<>();
                          arrayList.add(county);
                          streetMap.put(county.areaCode,arrayList);
                        }
                      }
                    }
                    ArrayList arrayList = streetMap.get(item.code);
                    notifyAdapter(arrayList);

                    if (mProgressDialog != null) {
                      ThreadHelper.getInstance().runOnUiPostDelayed(new Runnable() {
                        @Override
                        public void run() {
                          mProgressDialog.dismiss();
                        }
                      },1000);

                    }
                  }
                });
            }

            upTabStatus(item.name);
            indicatorAnim();
          }
        });

      }
    };

    recyclerView.setAdapter(mAdapter);
    getProvinceList(new Consumer>() {
      @Override
      public void accept(ArrayList list) throws Exception {
        notifyAdapter(proviceList);
      }
    });
  }


  private void initClick() {
    ivClose.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        closeDialog();
      }
    });

    llContainer.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        closeDialog();
      }
    });

  }

  private void notifyAdapter(ArrayList list){
    mAdapter.getData().clear();
    mAdapter.addData(list);
  }

  //indicator 动画
  private void indicatorAnim(){
    switch (currentTab){
      case 1:
        float text = textViewProvince.getPaint().measureText(textProvince);
        indicator.animate().translationX(text+UIUtil.dip2pxf(Objects.requireNonNull(getContext()),21f)).setDuration(200).start();
        break;
      case 2:
        float measureText = textViewProvince.getPaint().measureText(textProvince);
        float measureText1 = textViewCity.getPaint().measureText(textCity);
        indicator.animate().translationX(measureText+measureText1+UIUtil.dip2pxf(Objects.requireNonNull(getContext()),42f)).setDuration(200).start();
        break;
      case 3:
        float measure = textViewProvince.getPaint().measureText(textProvince);
        float measure1 = textViewCity.getPaint().measureText(textCity);
        float measure2 = textViewArea.getPaint().measureText(textArea);
        indicator.animate().translationX(measure+measure1+measure2+UIUtil.dip2pxf(Objects.requireNonNull(getContext()),63f)).setDuration(200).start();

    }
  }

  private void upTabStatus(String name){
    switch (currentTab){
      case 0:
        textProvince=name;
        textViewProvince.setText(name);
        textViewCity.setVisibility(View.VISIBLE);
        currentTab =1;
        break;
      case 1:
        textCity=name;
        textViewCity.setText(name);
        textViewArea.setVisibility(View.VISIBLE);
        currentTab =2;
        break;
      case 2:
        textArea=name;
        textViewArea.setText(name);
        textViewStreet.setVisibility(View.VISIBLE);
        currentTab=3;
        break;
      case 3:
        textStreet=name;
        textViewStreet.setText(name);
        dismissAllowingStateLoss();
        break;

    }
    textViewProvince.setSelected(currentTab==0);
    textViewCity.setSelected(currentTab==1);
    textViewArea.setSelected(currentTab==2);
    textViewStreet.setSelected(currentTab==3);
  }

  private void getProvinceList(Consumer> consumer){
    Disposable subscribe1 = Observable.create((new ObservableOnSubscribe() {
      public final void subscribe(@NonNull ObservableEmitter it) {
        if (proviceList.isEmpty()) {
          String json = getJson("address/provinces.json", getContext());
          ArrayList list = fromJson(json,new TypeToken>(){}.getType());
          if (list==null) {
            list =new ArrayList<>();
          }
          proviceList.addAll(list);
        }

        if (!proviceList.isEmpty()) {
          it.onNext(proviceList);
        }
      }
    })).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(consumer, new Consumer() {
      @Override
      public void accept(Throwable throwable) throws Exception {

      }
    });
    compositeDisposable.add(subscribe1);
  }

  private void getCityList(Consumer> consumer){
    Disposable subscribe1 = Observable.create((new ObservableOnSubscribe() {
      public final void subscribe(@NonNull ObservableEmitter it) {
        if (cityList.isEmpty()) {
          String json = getJson("address/cities.json", getContext());
          ArrayList list = fromJson(json,new TypeToken>(){}.getType());
          if (list==null) {
            list =new ArrayList<>();
          }
          cityList.addAll(list);
        }

        if (!cityList.isEmpty()) {
          it.onNext(cityList);
        }
      }
    })).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(consumer, new Consumer() {
      @Override
      public void accept(Throwable throwable) throws Exception {

      }
    });

    compositeDisposable.add(subscribe1);
  }

  private void getAreaList(Consumer> consumer){
    Disposable subscribe1 = Observable.create((new ObservableOnSubscribe() {
      public final void subscribe(@NonNull ObservableEmitter it) {
        if (areaList.isEmpty()) {
          String json = getJson("address/areas.json", getContext());
          ArrayList list = fromJson(json,new TypeToken>(){}.getType());
          if (list==null) {
            list =new ArrayList<>();
          }
          areaList.addAll(list);
        }

        if (!areaList.isEmpty()) {
          it.onNext(areaList);
        }
      }
    })).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(consumer, new Consumer() {
      @Override
      public void accept(Throwable throwable) throws Exception {

      }
    });
    compositeDisposable.add(subscribe1);
  }

  private void getStreetList(Consumer> consumer){
    Disposable subscribe1 = Observable.create((new ObservableOnSubscribe() {
      public final void subscribe(@NonNull ObservableEmitter it) {
        if (streetList.isEmpty()) {
          String json = getJson("address/streets.json", getContext());
          ArrayList list = fromJson(json,new TypeToken>(){}.getType());
          if (list==null) {
            list =new ArrayList<>();
          }
          streetList.addAll(list);
        }

        if (!streetList.isEmpty()) {
          it.onNext(streetList);
        }
      }
    })).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(consumer, new Consumer() {
      @Override
      public void accept(Throwable throwable) throws Exception {

      }
    });
    compositeDisposable.add(subscribe1);

  }


  public String getJson(String fileName, Context context) {
    StringBuilder stringBuilder = new StringBuilder();
    try {
      InputStream is = context.getAssets().open(fileName);
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
      String line;
      while ((line = bufferedReader.readLine()) != null) {
        stringBuilder.append(line);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

    return stringBuilder.toString();
  }


  @Nullable
  public  T fromJson(String json, Type typeOfT) {
    try {
      return initGson().fromJson(json, typeOfT);
    } catch (JsonSyntaxException e) {
      e.printStackTrace();
    }
    return null;
  }


  private Gson initGson(){
    GsonBuilder gsOnBuilder= new GsonBuilder();
    try {
      Class builder = gsonBuilder.getClass();
      Field f = builder.getDeclaredField("instanceCreators");
      f.setAccessible(true);
      Map> val = (Map>) f.get(gsonBuilder);//得到此属性的值
      //注册数组的处理器
      ConstructorConstructor cOnstructorConstructor= new ConstructorConstructor(val);
//      gsonBuilder.registerTypeAdapterFactory(new ReflectiveTypeAdapterFactory(constructorConstructor, FieldNamingPolicy.IDENTITY,
//          Excluder.DEFAULT,new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor)));
      gsonBuilder.registerTypeAdapterFactory(new MapTypeAdapterFactory(constructorConstructor,false));
      gsonBuilder.registerTypeAdapterFactory(new CollectionTypeAdapterFactory(constructorConstructor));
//      gsonBuilder.registerTypeAdapter(String.class,new StringTypeAdapter());
      gsonBuilder.registerTypeAdapter(int.class,new IntegerTypeAdapter());
      gsonBuilder.registerTypeAdapter(Integer.class,new IntegerTypeAdapter());
//      gsonBuilder.registerTypeAdapter(long.class,new LongTypeAdapter());
//      gsonBuilder.registerTypeAdapter(Long.class,new LongTypeAdapter());
//      gsonBuilder.registerTypeAdapter(double.class,new DoubleTypeAdapter());
//      gsonBuilder.registerTypeAdapter(Double.class,new DoubleTypeAdapter());
//      gsonBuilder.registerTypeAdapter(boolean.class,new BooleanTypeAdapter());
//      gsonBuilder.registerTypeAdapter(Boolean.class,new BooleanTypeAdapter());
//      gsonBuilder.registerTypeAdapter(float.class,new FloadTypeAdapter());
//      gsonBuilder.registerTypeAdapter(Float.class,new FloadTypeAdapter());

    } catch (NoSuchFieldException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return gsonBuilder.enableComplexMapKeySerialization().create();
  }


  public void closeDialog() {
      clContainer.animate().translationY(measuredHeight).setDuration(150).withEndAction(new Runnable() {
        @Override
        public void run() {
          dismissAllowingStateLoss();
        }
      }).start();
  }


  public void dismissAllowingStateLoss() {
    super.dismissAllowingStateLoss();
    if (!TextUtils.isEmpty(textProvince) && !TextUtils.isEmpty(textCity) && !TextUtils.isEmpty(textArea)&&!TextUtils.isEmpty(textStreet)) {
      listener.onSelect(textProvince, textCity, textCity,textStreet);
    }
    listener.isMissing();
    compositeDisposable.dispose();
  }


  public void setOnSelectListener(OnSelectListener listener) {
    this.listener = listener;
  }

  public void setHeight(int top) {

  }

  @Override
  public void onDestroyView() {
    super.onDestroyView();
    unbinder.unbind();
  }

  public interface OnSelectListener {
    int getHeight();

    void onSelect(String province, String city, String area,String street);

    void isMissing();
  }

}

使用方法

private void addressDialog() {
    AddressDialog addressDialog =new AddressDialog();
    addressDialog.setOnSelectListener(new AddressDialog.OnSelectListener() {
      @Override
      public int getHeight() {
        return 0;
      }

      @SuppressLint("SetTextI18n")
      @Override
      public void onSelect(String province, String city, String area, String street) {
        tvPositionRtrCommunity.setText(province+" "+city+" "+area+" "+street);
      }

      @Override
      public void isMissing() {
        isShowDialog = true;
      }
    });
    addressDialog.show(getSupportFragmentManager(),AddressDialog.class.getSimpleName());
}

资源下载:四级联动地址选择器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
  • 在Android中解析Gson解析json数据是很方便快捷的,可以直接将json数据解析成java对象或者集合。使用Gson解析json成对象时,默认将json里对应字段的值解析到java对象里对应字段的属性里面。然而,当我们自己定义的java对象里的属性名与json里的字段名不一样时,我们可以使用@SerializedName注解来将对象里的属性跟json里字段对应值匹配起来。本文介绍了使用@SerializedName注解解析json数据的方法,并给出了具体的使用示例。 ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
author-avatar
毛小猫TTN
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有