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

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

效果如下:

代码传送阵:

address_selector.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/ll_container"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:fitsSystemWindows="true"

android:alpha="0"

android:background="#b2000000"

android:orientation="vertical"

tools:alpha="1">

<android.support.constraint.ConstraintLayout

android:id="@+id/cl_container"

android:clickable="true"

android:focusable="true"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@drawable/selector_bg">

<TextView

android:id="@+id/textViewProvince"

android:layout_width="wrap_content"

android:layout_height="@dimen/dp_42"

android:layout_marginStart="@dimen/dp_18"

android:ellipsize="end"

android:paddingTop="@dimen/dp_13"

android:maxWidth="@dimen/dp_80"

android:maxLines="1"

android:text="请选择"

android:textColor="@drawable/selector_item_text_color"

android:textSize="@dimen/sp_14"

android:textStyle="bold"

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintTop_toTopOf="parent"

tools:text="请选择请选择"

tools:visibility="visible" />

<TextView

android:id="@+id/textViewCity"

android:layout_width="wrap_content"

android:layout_height="@dimen/dp_44"

android:layout_marginStart="@dimen/dp_21"

android:ellipsize="end"

android:paddingTop="@dimen/dp_13"

android:maxWidth="@dimen/dp_80"

android:maxLines="1"

android:text="请选择"

android:textColor="@drawable/selector_item_text_color"

android:textSize="@dimen/sp_14"

android:textStyle="bold"

android:visibility="invisible"

app:layout_constraintLeft_toRightOf="@id/textViewProvince"

app:layout_constraintTop_toTopOf="parent"

tools:text="请选择请选择"

tools:visibility="visible" />

<TextView

android:id="@+id/textViewArea"

android:layout_width="wrap_content"

android:layout_height="@dimen/dp_44"

android:layout_marginStart="@dimen/dp_21"

android:ellipsize="end"

android:paddingTop="@dimen/dp_13"

android:maxWidth="@dimen/dp_80"

android:maxLines="1"

android:text="请选择"

android:textColor="@drawable/selector_item_text_color"

android:textSize="@dimen/sp_14"

android:textStyle="bold"

android:visibility="invisible"

app:layout_constraintLeft_toRightOf="@id/textViewCity"

app:layout_constraintTop_toTopOf="parent"

tools:text="请选择请选择"

tools:visibility="visible" />

<TextView

android:id="@+id/textViewStreet"

android:layout_width="wrap_content"

android:layout_height="@dimen/dp_44"

android:layout_marginStart="@dimen/dp_21"

android:ellipsize="end"

android:paddingTop="@dimen/dp_13"

android:maxWidth="@dimen/dp_80"

android:maxLines="1"

android:text="请选择"

android:textColor="@drawable/selector_item_text_color"

android:textSize="@dimen/sp_14"

android:textStyle="bold"

android:visibility="invisible"

app:layout_constraintLeft_toRightOf="@id/textViewArea"

app:layout_constraintTop_toTopOf="parent"

tools:text="请选择请选择"

tools:visibility="visible" />

<android.support.v7.widget.AppCompatImageView

android:id="@+id/iv_close"

android:layout_width="@dimen/dp_23"

android:layout_height="@dimen/dp_23"

android:layout_marginTop="@dimen/dp_12"

android:layout_marginEnd="@dimen/dp_12"

android:padding="@dimen/dp_5"

android:src="@drawable/address_close"

app:layout_constraintRight_toRightOf="parent"

app:layout_constraintTop_toTopOf="parent" />

<View

android:id="@+id/indicator"

android:layout_width="@dimen/dp_24"

android:layout_height="@dimen/dp_2"

android:background="#000000"

app:layout_constraintLeft_toLeftOf="@id/textViewProvince"

app:layout_constraintTop_toBottomOf="@id/textViewProvince" />

<View

android:id="@+id/divider"

android:layout_width="match_parent"

android:layout_height="0.5dp"

android:background="#e5e5e5"

app:layout_constraintTop_toBottomOf="@id/indicator" />

<android.support.v7.widget.RecyclerView

android:id="@+id/recycler_view"

android:layout_width="match_parent"

android:layout_height="0dp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintTop_toBottomOf="@id/divider" />

</android.support.constraint.ConstraintLayout>

</LinearLayout>

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<County> proviceList = new ArrayList<>();

// 市

private ArrayList<County> cityList = new ArrayList<>();

private ConcurrentHashMap<String, ArrayList<County>> cityMap = new ConcurrentHashMap<>();

// 区

private ArrayList<County> areaList = new ArrayList<>();

private ConcurrentHashMap<String, ArrayList<County>> areaMap = new ConcurrentHashMap<>();

//街道

private ArrayList<County> streetList = new ArrayList<>();

private ConcurrentHashMap<String, ArrayList<County>> streetMap = new ConcurrentHashMap<>();

private BaseQuickAdapter<County, BaseViewHolder> 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 ? 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<County, BaseViewHolder>(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<ArrayList<County>>() {

@Override

public void accept(ArrayList<County> counties) throws Exception {

// 本地是否存在

if (cityMap.containsKey(item.code)){

ArrayList<County> 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<County> list = cityMap.get(item.code);

if (list != null) {

list.add(next);

cityMap.put(next.provinceCode, list);

}

} else {

@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")

ArrayList<County> listCounty = new ArrayList<>();

listCounty.add(next);

cityMap.put(next.provinceCode, listCounty);

}

}

}

ArrayList<County> list = cityMap.get(item.code);

notifyAdapter(list);

}

});

break;

case 1:

getAreaList(new Consumer<ArrayList<County>>() {

@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")

@Override

public void accept(ArrayList<County> list) throws Exception {

if (areaMap.containsKey(item.code)) {

ArrayList<County> 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<County> countyArrayList = areaMap.get(item.code);

if (countyArrayList != null) {

countyArrayList.add(county);

areaMap.put(county.code, countyArrayList);

}

}else {

ArrayList<County> arrayList = new ArrayList<>();

arrayList.add(county);

areaMap.put(county.cityCode,arrayList);

}

}

}

ArrayList<County> 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<ArrayList<County>>() {

@Override

public void accept(ArrayList<County> list) throws Exception {

if (streetMap.containsKey(item.code)) {

ArrayList<County> 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<County> countyArrayList = streetMap.get(item.code);

if (countyArrayList != null) {

countyArrayList.add(county);

streetMap.put(county.code, countyArrayList);

}

}else {

ArrayList<County> arrayList = new ArrayList<>();

arrayList.add(county);

streetMap.put(county.areaCode,arrayList);

}

}

}

ArrayList<County> 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<ArrayList<County>>() {

@Override

public void accept(ArrayList<County> 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<County> 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<ArrayList<County>> 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<County> list = fromJson(json,new TypeToken<ArrayList<County>>(){}.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<Throwable>() {

@Override

public void accept(Throwable throwable) throws Exception {

}

});

compositeDisposable.add(subscribe1);

}

private void getCityList(Consumer<ArrayList<County>> 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<County> list = fromJson(json,new TypeToken<ArrayList<County>>(){}.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<Throwable>() {

@Override

public void accept(Throwable throwable) throws Exception {

}

});

compositeDisposable.add(subscribe1);

}

private void getAreaList(Consumer<ArrayList<County>> 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<County> list = fromJson(json,new TypeToken<ArrayList<County>>(){}.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<Throwable>() {

@Override

public void accept(Throwable throwable) throws Exception {

}

});

compositeDisposable.add(subscribe1);

}

private void getStreetList(Consumer<ArrayList<County>> 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<County> list = fromJson(json,new TypeToken<ArrayList<County>>(){}.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<Throwable>() {

@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> 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<Type, InstanceCreator<?>> val = (Map<Type, InstanceCreator<?>>) 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());

}

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

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

以上是 Android实现四级联动地址选择器 的全部内容, 来源链接: utcz.com/p/243088.html

回到顶部