android自定义4级联动,使用Android如何实现四级联动地址选择器

使用Android如何实现四级联动地址选择器

发布时间:2020-10-28 15:05:05

来源:亿速云

阅读:122

作者:Leah

使用Android如何实现四级联动地址选择器?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

效果如下:

fa9af5f76337fb7368a5e2c214bc053a.png

代码传送阵:

address_selector.xml

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: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">

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" />

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" />

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" />

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: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" />

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" />

android:id="@+id/divider"

android:layout_width="match_parent"

android:layout_height="0.5dp"

android:background="#e5e5e5"

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

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" />

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 ? 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());

}

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android四级联动地址选择器是一种用户界面组件,用于实现在选择省、市、区和街道地址时的联动效果。它通常被用于用户注册、编辑个人信息等场景中,方便用户快速选择地址信息。 实现四级联动地址选择器,首先需要使用Android提供的相关控件,如Spinner、ListView等。通过Spinner控件可以实现省、市、区和街道的选择,通过ListView控件或其他容器控件可以展示对应的地址列表。 其次,需要准备好相应的地址数据。这些数据可以通过数据库查询或者网络请求获取,也可以事先定义在本地的资源文件中。其中,省份数据为一级数据,市区数据为二级数据,区县数据为三级数据,街道数据为四级数据。每一个省份都包含若干个市,每一个市都包含若干个区县,每一个区县都包含若干个街道。 然后,需要为每一个控件设置适配器,将数据源与控件进行绑定。在选择省份的时候,根据选择的省份态加载对应的市区数据,并更新市区控件的适配器。同理,选择市区时,态加载对应的区县数据,并更新区县控件的适配器。选择区县时,态加载对应的街道数据,并更新街道控件的适配器。 最后,在用户选择了最终的地址信息后,可以获取对应的地址数据,进行后续的处理。可以通过监听事件或者点击事件的方式,获取用户选择的地址信息,并进行保存或者其他操作。 通过以上的步骤,就可以实现一个简单的Android四级联动地址选择器。用户可以根据自己的需要进行修改和扩展,实现更加复杂的地址选择功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值