用listview做联动菜单,省市区为例,附带省市区json文件
来源:互联网 发布:拓扑算法 编辑:程序博客网 时间:2024/06/03 03:21
闲话
之前没做过联动菜单,最近项目中要用到几个,百度网上有不少现成的控件实现,有用到spinner的,还有用到其他控件的,不过风格不是我需要的,索性自己来实现一下,虽然不如其他大神的方法简便,但自己写的,还是更喜欢。
正文
制作数据源
首先要有级联用的数据源,我这里有一份,我忘记是从哪位大神资源上下载的了,感谢,自己制作一份json数据也行:
省市区json下载
可以把这份json文档放在项目目录的assets下,以便调取。
布局文件
因为用到listview作为展示级联的控件,因此,主布局很简单,只用建立3个listview。
<?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" xmlns:tools="http://schemas.android.com/tools" android:orientation="horizontal" android:background="@color/colorBackground"> <ListView android:layout_marginLeft="10dp" android:layout_marginRight="5dp" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:divider="@color/colorBackground" android:dividerHeight="2dp" android:id="@+id/lvProvince" /> <ListView android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:divider="@color/colorBackground" android:dividerHeight="2dp" android:id="@+id/lvCity"/> <ListView android:layout_marginLeft="5dp" android:layout_marginRight="10dp" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:divider="@color/colorBackground" android:dividerHeight="2dp" android:id="@+id/lvArea"/></LinearLayout>
然后是item子布局,写demo懒一些,每个listview公用一个item布局。
我写布局的时候,不知道为什么,如果把textview充满父布局,然后让文字居中显示android:gravity=”center”,这样写感觉没什么问题,但实际测试时发现,第一次展示数据的时候,不会有什么问题,但是点击几次之后,有些item就不会在执行居中操作了,很奇怪,我也不知道为什么,所以才修改位textview自适应,布局居中android:layout_centerInParent=”true”
<?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="wrap_content" android:background="@color/colorWhite"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="@color/colorWord" android:textSize="16sp" android:text="省市区" android:gravity="center" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:id="@+id/tvPCA"/></RelativeLayout>
Adapter
adapter也很简单,继承BaseAdapter。怎样给选中的item修改颜色,以便提醒用户,我的处理方法是在adapter中添加一个方法setSelectPosition(int position),传入点击的item,在getView中,判断当前item是否是点击的item,如果是,就设置选中的颜色。稍微有点麻烦,不过效果还可以。
public void setSelectPosition(int position){ this.selectPosition=position; }
整个adapter代码
public class AdapterForPCA extends BaseAdapter { private List<String> list=null; private Context context; private int selectPosition; public AdapterForPCA(List<String> list, Context context){ this.list=list; this.context=context; } public void setSelectPosition(int position){ this.selectPosition=position; } @Override public int getCount() { if (list!=null){ return list.size(); } return 0; } @Override public Object getItem(int i) { return null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder=null; if (view==null){ view= LayoutInflater.from(context).inflate(R.layout.item_listview_province_city_area,null); viewHolder=new ViewHolder(); viewHolder.tvPCA=Utils.findView(view,R.id.tvPCA); view.setTag(viewHolder); }else { viewHolder=(ViewHolder)view.getTag(); } viewHolder.tvPCA.setText(list.get(i)); viewHolder.tvPCA.setGravity(Gravity.CENTER); //为了让点击的item显示不同的颜色,必须在item点击后 重新 notifyDataSetChange if (selectPosition==i){ viewHolder.tvPCA.setBackgroundColor(context.getResources().getColor(R.color.colorButton)); view.setBackgroundColor(context.getResources().getColor(R.color.colorButton)); viewHolder.tvPCA.setTextColor(context.getResources().getColor(R.color.colorWhite)); }else { viewHolder.tvPCA.setBackgroundColor(context.getResources().getColor(R.color.colorWhite)); view.setBackgroundColor(context.getResources().getColor(R.color.colorWhite)); viewHolder.tvPCA.setTextColor(context.getResources().getColor(R.color.colorWord)); } return view; } class ViewHolder{ TextView tvPCA; }}
Activity应用
先从assets中读取数据源
/** * 从文本中读取 省市区城市列表 * @return */ private String readPCA(){ InputStream in=null; ByteArrayOutputStream out=null; try { in=getAssets().open("PCA.json"); out=new ByteArrayOutputStream(); byte[] b=new byte[1024]; int length=-1; while ((length=in.read(b))!=-1){ out.write(b,0,length); } return new String(out.toByteArray()); } catch (IOException e) { e.printStackTrace(); return null; } finally { if (in!=null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } }
读取之后先存在保存为JSON数组
try { jsonArrayP=new JSONArray(readPCA()); } catch (JSONException e) { e.printStackTrace(); }
然后分别获取省市区的列表
/** * 获取省列表 */ private void initListP(){ try { listP.clear(); if (jsonArrayP!=null) { for (int i = 0; i < jsonArrayP.length(); i++) { JSONObject objP = jsonArrayP.getJSONObject(i);//获取省份对象 listP.add(objP.getString("name"));//获取省份名字 } } } catch (JSONException e) { e.printStackTrace(); } } /** * 根据点击的省份,获取该省的城市列表 * @param provinceNum */ private void setListC(int provinceNum){ listC.clear(); try { jsonObjP=jsonArrayP.getJSONObject(provinceNum);//获取点击的省份对象 jsonArrayC=jsonObjP.getJSONArray("city");//获取该省份的城市数组 for (int i=0;i<jsonArrayC.length();i++){ JSONObject objC=jsonArrayC.getJSONObject(i);//获取城市数组的城市对象 listC.add(objC.getString("name"));//获取城市名字 } } catch (JSONException e) { e.printStackTrace(); } } /** * 根据点击的城市获得地区列表 * @param cityNum */ private void setListA(int cityNum){ listA.clear(); try { jsonObjC=jsonArrayC.getJSONObject(cityNum);//根据点击的城市对象 JSONArray arrayA=jsonObjC.getJSONArray("area");//获取该城市的地区列表 for (int i=0;i<arrayA.length();i++){ listA.add(arrayA.getString(i));//添加地区列表到list } } catch (JSONException e) { e.printStackTrace(); } }
最后做初始化UI 和 listview的点击事件,注释比较详细,就不一一说明了
private void initUI(){ try { jsonArrayP=new JSONArray(readPCA()); } catch (JSONException e) { e.printStackTrace(); } listP=new ArrayList<>(); initListP(); listC=new ArrayList<>(); pro=0; setListC(pro);//设置默认展示的省份,根据json数组的系列号 listA=new ArrayList<>(); city=0; setListA(city);//设置默认展示哪个城市的地区 lvProvince=Utils.findView(this,R.id.lvProvince); adapterP=new AdapterForPCA(listP,this); adapterP.setSelectPosition(pro);//设置默认选中的省份变颜色 lvProvince.setAdapter(adapterP); lvProvince.setOnItemClickListener(this); lvCity=Utils.findView(this,R.id.lvCity); adapterC=new AdapterForPCA(listC,this); adapterC.setSelectPosition(city);//设置默认选中的城市变颜色 lvCity.setAdapter(adapterC); lvCity.setOnItemClickListener(this); lvArea=Utils.findView(this,R.id.lvArea); adapterA=new AdapterForPCA(listA,this); adapterA.setSelectPosition(area);//设置默认选中的地区变颜色 lvArea.setAdapter(adapterA); lvArea.setOnItemClickListener(this); } /** * 每个list 点击事件 * @param adapterView * @param view * @param i * @param l */ @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { switch (adapterView.getId()){ case R.id.lvProvince://点击省列表 pro=i;//获得选择的省的item adapterP.setSelectPosition(pro);//为了让选择的item显示不同的颜色 //每一次选择省,都需要把 之前选择的市和区的item初始化为0,默认选择第一个 city=0; area=0; adapterC.setSelectPosition(city);//为了让选择的item显示不同的颜色 adapterA.setSelectPosition(area);//为了让选择的item显示不同的颜色 //获得点击的省份对应的 城市列表 setListC(pro); //点击省份,显示城市,由于还没有点击城市,所以默认选择第一个城市,展示第一个城市的区列表 setListA(city); //点击省份,需要三个listview都刷新data ,以便执行 setSelectPosition ,刷新选择的项目的颜色 adapterP.notifyDataSetChanged(); adapterC.notifyDataSetChanged(); adapterA.notifyDataSetChanged(); break; case R.id.lvCity: city=i;//点击的城市的item area=0;//由于还没有选择区,所以区默认选择第一个 adapterC.setSelectPosition(city);//为了让选择的item显示不同的颜色 adapterA.setSelectPosition(area);//为了让选择的item显示不同的颜色 setListA(i);//获取选择的城市的区列表 //点击城市,需要刷新 城市 和 区 listview, 以便执行 setSelectPosition ,刷新选择的项目的颜色 adapterC.notifyDataSetChanged(); adapterA.notifyDataSetChanged(); break; case R.id.lvArea: area=i;//点击的区 adapterA.setSelectPosition(area);////为了让选择的item显示不同的颜色 //点击城市,需要刷新 区 listview, 以便执行 setSelectPosition ,刷新选择的项目的颜色 adapterA.notifyDataSetChanged(); Toast.makeText(MainActivity.this, listP.get(pro)+""+listC.get(city)+""+listA.get(area), Toast.LENGTH_SHORT).show(); break; } }
好了,这样,一个简单的级联菜单就做好了,看看效果
- 用listview做联动菜单,省市区为例,附带省市区json文件
- 省市区三级联动json
- 省市区三级联动[JSON+Jquery]
- xml文件 省市区三级联动
- 省市区联动
- 用jQuery实现省市区三级联动(可做插件)
- 省市区三级联动菜单(附数据库)
- 省市区三级联动菜单(附数据库)
- 省市区三级联动菜单(附数据库)
- 省市区三级联动菜单(附数据库)
- 省市区三级联动菜单(附数据库)
- 省市区三级联动菜单(附数据库)
- JS+JSON 省市区 三级联动 SELECT
- JS+JSON 省市区 三级联动 SELECT
- 省市区-三级联动(json数据模拟)
- 省市区三级联动(数组、JSON实现)
- javascript实现省市区三级联动选择的代码(数据为模拟json数据)
- 用js实现全国省市区联动
- 【数据结构与算法学习笔记】PART2 向量(接口与实现,可扩充向量,无序向量,有序向量)
- String深入理解
- eclipse xml 注释快捷键
- TextView文本复制功能的实现方式
- Android Studio之gradle的配置与介绍
- 用listview做联动菜单,省市区为例,附带省市区json文件
- 用Fiddler查看 Android/iOS 网络请求
- webp格式图片转换问题解决方法
- Struts2参数封装
- python笔记之NUMPY中的掩码数组numpy.ma.mask
- 顺时针打印矩阵
- 写一个福利 Telegram 机器人
- 《深入体验java web 开发内幕》-1
- python导入模块