Android 省市区三级联动

本文介绍了一种使用JSON数据源实现地区选择功能的方法。通过三个并排的ListView展示省、市、区县数据,实现了从省级到区县级别的地区选择功能。

背景

最近因为业务需要,要实现选择到区县的功能,以前的常用数据库并不包含区县数据,所以自己特地到网上寻找包含区县数据的数据库文件。

本来想用常规读取SQLite的方式呈现数据,但是刚好浏览到json格式的数据,突发奇想,能不能用json数据来作为数据源呢?

说干就干,尝试了一番之后,终于把效果实现出来了,还是比较满意的。下面是效果图:

效果图

废话不多说,接下来说说如何实现的思路。

代码实现

我是用三个并排的listview,往里面填充区域数据的,这是主界面的布局

<?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="match_parent">

    <ListView
        android:id="@+id/lv_pro"
        android:layout_width="110dp"
        android:layout_height="wrap_content" />

    <ListView
        android:id="@+id/lv_city"
        android:layout_width="110dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/lv_pro" />

    <ListView
        android:id="@+id/lv_dis"
        android:layout_width="110dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/lv_city" />

</RelativeLayout>

说到这里,还有一点郁闷的地方,本来我是打算使用RecyclerView的,但是不知何故,并排放置三个RecyclerView,设置好设配器的时候,前面的RecyclerView无法显示出来了,很是郁闷。在此,如果有知道解决办法的童鞋,还望赐教一二。

界面弄完之后,接下来就写功能代码了,具体的实现如下:

package cn.zhuziyu.selectarea;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnItemClick;
import cn.zhuziyu.selectarea.model.CityData;
import cn.zhuziyu.selectarea.model.DistrictData;
import cn.zhuziyu.selectarea.model.ProvinceData;

/**
 * @author Zen
 * @date 2016/3/27 0027 15:05
 */
public class AreaActivity extends AppCompatActivity {


    @Bind(R.id.lv_city)
    ListView lvCity;
    @Bind(R.id.lv_pro)
    ListView lvPro;
    @Bind(R.id.lv_dis)
    ListView lvDis;

    private InputStreamReader reader;
    private Gson gson;

    private List<ProvinceData> proData;
    private List<CityData> cityData, cityCheckData;   //前者放置所有的城市数据,后者放置根据条件选择的城市数据
    private List<DistrictData> disData, disCheckData;//同上

    private List<String> proDatas;
    private List<String> cityDatas;
    private List<String> disDatas;

    private ArrayAdapter<String> cityAdapter, disAdapter;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_area);
        ButterKnife.bind(this);
        gson = new Gson();
        initView();
    }

    protected void initView() {
        //刚进来的时候,立刻给省的ListView填充数据
        try {
            Type proType = new TypeToken<ArrayList<ProvinceData>>() {
            }.getType();
            proData = getLocData("ProvinceData.json", proType);
            proDatas = new ArrayList<>();
            for (ProvinceData data : proData) {
                proDatas.add(data.getName());
            }
            lvPro.setAdapter(new ArrayAdapter<>(AreaActivity.this, android.R.layout.simple_list_item_1, proDatas));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //初始化另外两个ListView
        cityData = new ArrayList<>();
        cityDatas = new ArrayList<>();
        cityCheckData = new ArrayList<>();
        cityAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, cityDatas);
        lvCity.setAdapter(cityAdapter);

        disData = new ArrayList<>();
        disDatas = new ArrayList<>();
        disCheckData = new ArrayList<>();
        disAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, disDatas);
        lvDis.setAdapter(disAdapter);
    }

    /**
     * 省Listview的item点击事件
     *
     * @param position
     */
    @OnItemClick(R.id.lv_pro)
    void selectPro(int position) {
        Log.i("TAG", "Position:" + position);
        cityData.clear();//添加数据前,先删除旧数据
        cityDatas.clear();
        cityCheckData.clear();

        disDatas.clear();  //清除区的数据列表,并通知区更新数据
        disData.clear();
        disCheckData.clear();
        disAdapter.notifyDataSetChanged();
        try {
            int proId = proData.get(position).getProID();    //proId
            Type cityType = new TypeToken<ArrayList<CityData>>() {
            }.getType();
            cityData = getLocData("CityData.json", cityType);
            for (CityData data : cityData) {
                if (data.getProID() == proId) {      //根据proId,查找名下的城市
                    cityDatas.add(data.getName());
                    cityCheckData.add(data);
                }
            }
            cityAdapter.notifyDataSetChanged();    //通知listView更新数据
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnItemClick(R.id.lv_city)
    void selectCity(int position) {
        Log.i("TAG", "Position:" + position);
        disDatas.clear();
        disData.clear();
        disCheckData.clear();
        try {
            int cityId = cityCheckData.get(position).getCityID();
            Log.i("TAG", "cityId:" + cityId);
            Type disType = new TypeToken<ArrayList<DistrictData>>() {
            }.getType();
            disData = getLocData("DistrictData.json", disType);
            for (DistrictData data : disData) {
                if (data.getCityID() == cityId) {
                    disDatas.add(data.getDisName());
                    disCheckData.add(data);
                }
            }
            disAdapter.notifyDataSetChanged();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ButterKnife.unbind(this);
    }

    /**
     * 泛型方法,读取assets目录下的json文件,并填充到List中
     *
     * @param fileName
     * @param collectionType
     * @param <T>
     * @return
     * @throws IOException
     */
    public <T> List<T> getLocData(String fileName, Type collectionType) throws IOException {
        //获取assets目录下的json文件
        reader = new InputStreamReader(getAssets().open(fileName));
        List<T> locDatas = gson.fromJson(reader, collectionType);
        reader.close();
        return locDatas;
    }
}

整个实现过程就是这样子了,整个代码还有优化空间,不过迫于时间,就先这样了,等我有空了,在来优化一下代码,提升整体的读取性能。

工程已经放在Github上了,欢迎各位点评: 点我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值