近期项目中将要使用到地址联动选择器,就想自己用listview去简单实现一下功能,然后写了一个小demo。效果如下:
其实原理非常简单,就是对listview的滑动监听。然后做响应的操作就行了。
首先我们看看xml文件,简单的三个listview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ListView
android:id="@+id/lv_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ListView
android:id="@+id/lv_list2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ListView
android:id="@+id/lv_list3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2" />
LinearLayout>
<Button
android:id="@+id/bt_choose"
android:text="choose"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_showcity"
android:layout_width="match_parent"
android:layout_height="match_parent" />
LinearLayout>
需要用到的json文件,放在assets目录下。
地址:下载地址
将其读取出来,读取为字符串
private String InitData() {
StringBuffer sb = new StringBuffer();
AssetManager mAssetManager = this.getAssets();
try {
InputStream is = mAssetManager.open("city.json");
byte[] data = new byte[is.available()];
int len = -1;
while ((len = is.read(data)) != -1) {
sb.append(new String(data, 0, len, "utf-8"));
}
is.close();
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
将listview设置为固定显示5个条目:
private void initListview(final ListView listview,Adapter adapter) {
View listItem = adapter.getView(0, null, listview)
listItem.measure(0, 0)
int totalHei = (listItem.getMeasuredHeight() + listview.getDividerHeight()) * 5
listview.getLayoutParams().height = totalHei
listview.setSelection(mlist.size() * 1000)
}
创建3个集合,用于存放三个listview的数据,使用Gsonformat创建出json的bean类 :City。然后使用Gson解析json ,将数据加入到三个集合中:
String jsOnstr= InitData()
Gson gson = new Gson()
final City city = gson.fromJson(jsonstr, City.class)
for(City.CitylistBean citylistBean : city.getCitylist()) {
mlist.add(citylistBean.getP())
}
for (City.CitylistBean.CBean cBean : city.getCitylist().get(0).getC()) {
mlist2.add(cBean.getN())
}
if(city.getCitylist().get(0).getC().get(0).getA() != null) {
for (City.CitylistBean.CBean.ABean aBean :city.getCitylist().get(0).getC().get(0).getA()) {
mlist3.add(aBean.getS())
}
mdapter3 = new MyCityListAdapter(PickerActivity.this, mlist3)
lvTest3.setAdapter(mdapter3)
initListview(lvTest3, mdapter3)
} else {
mlist3.add("")
mdapter3 = new MyCityListAdapter(PickerActivity.this, mlist3)
lvTest3.setAdapter(mdapter3)
initListview(lvTest3, mdapter3)
}
这里的核心逻辑就是三个listview的滑动监听事件了:
listview1的监听:
//一级列表滑动监听
lvTest.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case SCROLL_STATE_IDLE:
//使得listview滑动停止时,可以显示5个完整的条目
lvTest.smoothScrollToPosition(lvTest.getFirstVisiblePosition())
popo = (lvTest.getFirstVisiblePosition()%mlist.size())
mlist2.clear()
for(City.CitylistBean.CBean cBean :city.getCitylist().get(popo).getC()) {
mlist2.add(cBean.getN())
}
mdapter2.notifyDataSetChanged()
pipi = (lvTest2.getFirstVisiblePosition()%mlist2.size())
mlist3.clear()
if(lvTest != null && mdapter3 != null && city.getCitylist().get(popo).getC().get(pipi).getA()!= null) {
for(City.CitylistBean.CBean.ABean aBean :city.getCitylist().get(popo).getC().get(pipi).getA()) {
mlist3.add(aBean.getS())
}
}else {
mlist3.add("")
}
mdapter3.notifyDataSetChanged()
break
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
})
listview2的监听:
lvTest2.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case SCROLL_STATE_IDLE:
//Log.d("TTT", "" + lvTest2.getFirstVisiblePosition())
lvTest2.smoothScrollToPosition(lvTest2.getFirstVisiblePosition())
pipi = (lvTest2.getFirstVisiblePosition()%mlist2.size())
mlist3.clear()
if(lvTest != null && mdapter3 != null && city.getCitylist().get(popo).getC().get(pipi).getA()!= null) {
for(City.CitylistBean.CBean.ABean aBean :city.getCitylist().get(popo).getC().get(pipi).getA()) {
mlist3.add(aBean.getS())
}
}else {
mlist3.add("")
}
mdapter3.notifyDataSetChanged()
break
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
})
listview3的监听:
lvTest3.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case SCROLL_STATE_IDLE:
lvTest3.smoothScrollToPosition(lvTest3.getFirstVisiblePosition());
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
}
主要逻辑就是这些,最后就是button设置监听,拿到每个列表选中的数据,显示在下方的textview中:
private String getChooseItemStr(ListView listView , List mlist) {
return mlist.get(listView.getFirstVisiblePosition()%mlist.size());
}
bt_choose = (Button) findViewById(R.id.bt_choose)
tvShowCity = (TextView) findViewById(R.id.tv_showcity)
bt_choose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String str1 = getChooseItemStr(lvTest,mlist)
String str2 = getChooseItemStr(lvTest2,mlist2)
String str3 = getChooseItemStr(lvTest3, mlist3)
str = str1+str2+str3 + "\r\n" + str
tvShowCity.setText(str)
}
})
以上就是demo的全部内容,当然demo实现的比较简单。有其他需求的可以继续修改代码。三级地址联动选择器有很多优秀的三方框架,本demo仅供参考。
源码下载地址