通常我们在外卖或者商城app会看到竖排二级列表的界面,点击左边列表的分类菜单,右边列表则会显示对应分类下的列表内容,这篇博文将对该功能的实现归纳和整理。

首先看下效果图:

android 二级联动城市 安卓二级联动_数据

android 二级联动城市 安卓二级联动_android 二级联动城市_02

在第一个页面选择最多三个标签,将书局塞到数组里返回上一个页面,然后就可以按照需求完成一系列操作。

下面说下实现步骤:

1.首先分析界面,是两个等比宽的列表,推荐使用recyclerview,右上角用来记录选择的标签个数,点击即可把数据返回上一个页面,未选择则返回空数组。

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="40dp">

        <TextView
            android:id="@+id/main_tv"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:gravity="center_vertical"
            android:text="确定(0/3)"
            android:textSize="16sp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:paddingRight="10dp"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="选择页面"
            android:textSize="18sp"
            android:layout_centerInParent="true"
            />
    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/main_recyclerviewAll"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/colorPrimaryDark" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/main_recyclerviewDetail"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>
</LinearLayout>

2.绘制列表item布局,因为就是简单的一个文字,只放一个居中的TextView,由于RecyclerView默认没有分隔线,我们在下面再放条高度为1px的view

item_recyclerview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:id="@+id/item_recyclerview_ll">

    <TextView
        android:id="@+id/item_recyclerview_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="textview"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="15dp"
        />
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#e3e3d3"
        android:layout_marginTop="15dp"/>

</LinearLayout>

3.新建FirstActivity,界面放个跳转至选择界面MainActivity的Button和用于显示从选择界面返回的标签数组的TextView

activity_first.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/first_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="去选择界面" />

    <TextView
        android:id="@+id/first_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

4.在选择界面MainActivity中,首先初始化控件。

tv = findViewById(R.id.main_tv);
recyclerviewAll = findViewById(R.id.main_recyclerviewAll);
recyclerviewDetail = findViewById(R.id.main_recyclerviewDetail);
LinearLayoutManager layout = new LinearLayoutManager(this);
LinearLayoutManager layout1 = new LinearLayoutManager(this);
recyclerviewAll.setLayoutManager(layout);
recyclerviewDetail.setLayoutManager(layout1);

5.设置列表数据bean,isFirst为是否选中的状态boolean值

package com.fantasychong.doublechecklisttest;

import java.io.Serializable;

/*
 *Crated by yedona on 2018/9/6
 */
public class ListBean implements Serializable {

    private String name;
    private boolean isSelect;

    public ListBean(String name, boolean isSelect) {
        this.name = name;
        this.isSelect = isSelect;
    }

    public boolean isSelect() {
        return isSelect;
    }

    public void setSelect(boolean select) {
        isSelect = select;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

5.设置左列表(一级)的数据,因为第一个数据标签默认选中,所以我们设置isSelect为true。

/**
 * 设置左列表数据
 */
private void initAllList() {
    allList = new ArrayList<>();
    AllListBean bean = new AllListBean("英雄联盟", true);
    allList.add(bean);
    AllListBean bean1 = new AllListBean("仙剑奇侠传", false);
    allList.add(bean1);
    AllListBean bean2 = new AllListBean("大航海时代", false);
    allList.add(bean2);
    AllListBean bean3 = new AllListBean("太阁立志传", false);
    allList.add(bean3);
    AllListBean bean4 = new AllListBean("战国无双", false);
    allList.add(bean4);
    AllListBean bean5 = new AllListBean("三国志", false);
    allList.add(bean5);
    AllListBean bean6 = new AllListBean("最终幻想", false);
    allList.add(bean6);
    AllListBean bean7 = new AllListBean("幻想传说", false);
    allList.add(bean7);
}

6.设置左右列表的通用adapter,这里推荐继承BaseQuickApdater,精简易操作。

package com.fantasychong.doublechecklisttest;

import android.content.Context;
import android.graphics.Color;
import android.support.annotation.Nullable;
import android.widget.TabHost;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import java.util.List;

/*
 *Crated by yedona on 2018/9/6
 */
public class ListAdapter extends BaseQuickAdapter<AllListBean, BaseViewHolder> {

    private final Context context;
    private final List<AllListBean> data;

    public ListAdapter (Context context, @Nullable List<AllListBean> data) {
        super(R.layout.item_recyclerview, data);
        this.context= context;
        this.data= data;
    }

    @Override
    protected void convert(BaseViewHolder helper, AllListBean item) {
        helper.setText(R.id.item_recyclerview_tv, item.getName())
                .setBackgroundColor(R.id.item_recyclerview_ll, item.isSelect()? Color.WHITE: Color.GRAY);
    }
}

在convert方法中设置是否选中后的背景颜色,选中设为白色white,反之设为灰色gray。

7.把数据塞到左recyclerView中,这样左列表可以呈现我们的塞进去的数据。

adapterAll = new ListAdapter (MainActivity.this, allList);
recyclerviewAll.setAdapter(adapterAll);

8.设置左列表的点击事件,当选中时标签会变为白色,并且上个选中标签会设置成未选中状态,即为灰色。注意这里要添加notifyDataSetChanged方法通知adapter刷新。

adapterAll.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        if (perPosition != position) {
            allList.get(perPosition).setSelect(false);
            allList.get(position).setSelect(true);
            adapterAll.notifyDataSetChanged();
            perPosition = position;
        }
    }
});

9.这样就完成了左列表显示并选中未选中的功能实现,接下来我们配置右(二级)列表。

我们初衷是进入页面时,左列表直接显示数据,右列表也要显示左列表的第一个分类下的数据,更改左列表标签,右列表的数据也会随之更改。

所以我们先把左列表第一个标签下的内容塞到右列表中让它呈现。

adapterAll.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        if (perPosition != position) {
            allList.get(perPosition).setSelect(false);
            allList.get(position).setSelect(true);
            adapterAll.notifyDataSetChanged();
            //设置右列表数据
            initDetailList(position);
            adapterDetail.notifyDataSetChanged();
            perPosition = position;
        }
    }
});
adapterDetail = new ListAdapter(MainActivity.this, detailList);
recyclerviewDetail.setAdapter(adapterDetail);

10.这样进入界面两个列表都会显示数据了,接下来做二级列表的选中和取消选中功能,因为二级列表要多选,所以可设置多个标签同时选中状态,同时把选中标签塞到一个checklist中,用于返回上个页面FirstActivity中,记着实时更新右上角的选中个数文本。

adapterDetail.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        if (detailList.get(position).isSelect()){
            checkList.remove(detailList.get(position).getName());
        }else{
            if (checkList.size()== 3) {
                Toast.makeText(MainActivity.this, "最多只能选择三个", Toast.LENGTH_SHORT).show();
                return;
            }
            checkList.add(detailList.get(position).getName());
        }
        detailList.get(position).setSelect(!detailList.get(position).isSelect());
        adapterDetail.notifyDataSetChanged();
    }
});

11.接下来要做他们的联动,当一级列表点击时,二级列表数据会更新,所以我们先清空二级列表数据list,再把一级列表position对应的数据塞到二级列表数据list,把已选中标签塞到一个checklist中,用于返回上一个页面FirstActivity中。

/**
 * 设置右列表数据
 */
private void initDetailList(int position) {
    detailList.clear();
    switch (position) {
        case 0:
            ListBean bean = new ListBean("暗夜猎手薇恩", false);
            detailList.add(bean);
            ListBean bean1 = new ListBean("暴走萝莉金克丝", false);
            detailList.add(bean1);
            ListBean bean2 = new ListBean("皮城女警凯瑟琳", false);
            detailList.add(bean2);
            ListBean bean3 = new ListBean("放逐之刃锐雯", false);
            detailList.add(bean3);
            break;
        case 1:
            ListBean bean4 = new ListBean("李逍遥", false);
            detailList.add(bean4);
            ListBean bean5 = new ListBean("赵灵儿", false);
            detailList.add(bean5);
            ListBean bean6 = new ListBean("林月如", false);
            detailList.add(bean6);
            ListBean bean7 = new ListBean("阿奴", false);
            detailList.add(bean7);
            break;
        case 2:
            ListBean bean8 = new ListBean("拉斐尔卡斯特路", false);
            detailList.add(bean8);
            ListBean bean9 = new ListBean("丽璐阿歌特", false);
            detailList.add(bean9);
            ListBean bean10 = new ListBean("李华梅", false);
            detailList.add(bean10);
            ListBean bean11 = new ListBean("赫德拉姆约阿奇姆柏格斯统", false);
            detailList.add(bean11);
            ListBean bean12 = new ListBean("蒂雅瓦曼恰斯卡", false);
            detailList.add(bean12);
            break;
        case 3:
            ListBean bean13 = new ListBean("丰臣秀吉", false);
            detailList.add(bean13);
            ListBean bean14 = new ListBean("织田信长", false);
            detailList.add(bean14);
            ListBean bean15 = new ListBean("真田幸村", false);
            detailList.add(bean15);
            ListBean bean16 = new ListBean("武田信玄", false);
            detailList.add(bean16);
            ListBean bean17 = new ListBean("本多忠胜", false);
            detailList.add(bean17);
            break;
        case 4:
            ListBean bean18 = new ListBean("上杉谦信", false);
            detailList.add(bean18);
            break;
        case 5:
            ListBean bean19 = new ListBean("赵云", false);
            detailList.add(bean19);
            break;
        case 6:
            ListBean bean20 = new ListBean("萨菲罗斯", false);
            detailList.add(bean20);
            break;
        case 7:
            ListBean bean21 = new ListBean("达尔斯", false);
            detailList.add(bean21);
            break;
        default:
            break;
    }
}

12.把initDetailList方法放到一级列表的onitemclicklistener中,同时一级列表切换时,清空二级列表的已选中标签数组checklist。

adapterAll.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        if (perPosition != position) {
            allList.get(perPosition).setSelect(false);
            allList.get(position).setSelect(true);
            adapterAll.notifyDataSetChanged();
            //设置右列表数据
            initDetailList(position);
            checkList.clear();
            tv.setText("确定(0/3)");
            adapterDetail.notifyDataSetChanged();
            perPosition = position;
        }
    }
});

13.这下联动已经完成,设置右上角个数文本的点击事件,使用setResult方法传递checklist。

tv.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent= new Intent();
        intent.putExtra("list", checkList.toString());
        setResult(1, intent);
        finish();
    }
});

14.在FirstActivity中接受list并显示在textview上,可以根据实际需求做相应操作。

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (data== null){
        return;
    }
    if (requestCode== 1){
        tv.setText(data.getStringExtra("list"));
        Log.d("listlistlist", data.getStringExtra("list"));
    }
}

至此全部完成,Demo附上。