android 一个页面内 多个listview的实现

如果很平常的两个listview组件竖直放在linearLayout布局中,结果是:

两个listview 很独立,中间似乎有个分割线,完全吧他们分离了,各自独立滚动,如果上面的listview把整个屏幕占据了,那么下面的listview永远滚不上来了,看不到了。


网上关于这个话题大约有两种方法解决:

(1)有多少个listview就用多少个listview组件,然后放在一个LinearLayout布局里面,linearLayout布局在放入Scrollview中。

这样做,必须先计算出每个listview被对应的adapter适配之后的实际高度,然后设置listview为这个高度。再放入scrollview中ok了。

(2)不管有多少个listview,都放在一个listview,用一个adapter适配,在listview组件对应的数据存储结构list中,设置flag标志位,在adapter中再对不同的flag做不同的适配。


一开始,项目中使用的第一种方法,随着项目的进行,发现第一种方法会在很多种情况下不适应,最严重的问题,就是第一种方法非常耗时,已经到了一种无可忍受的地步了。

一个很常见的例子,城市列表,有两个list:热门城市、全部城市


假如用第一种方法,先计算两个listview在对应的adapter适配后的高度:

[java]   view plain copy
  1. public static void setListViewHeightBasedOnChildren(ListView listView) {  
  2.     ListAdapter listAdapter = listView.getAdapter();  
  3.     if (listAdapter == null) {  
  4.         return;  
  5.     }  
  6.     int totalHeight = 0;  
  7.     for (int i = 0; i < listAdapter.getCount(); i++) {  
  8.         View listItem = listAdapter.getView(i, null, listView);  
  9.         listItem.measure(00);  
  10.         totalHeight += listItem.getMeasuredHeight();  
  11.     }  
  12.   
  13.     ViewGroup.LayoutParams params = listView.getLayoutParams();  
  14.     params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));  
  15.     listView.setLayoutParams(params);  
  16. }  
[java]   view plain copy
  1. public static void setListViewHeightBasedOnChildren(ListView listView) {  
  2.     ListAdapter listAdapter = listView.getAdapter();  
  3.     if (listAdapter == null) {  
  4.         return;  
  5.     }  
  6.     int totalHeight = 0;  
  7.     for (int i = 0; i < listAdapter.getCount(); i++) {  
  8.         View listItem = listAdapter.getView(i, null, listView);  
  9.         listItem.measure(00);  
  10.         totalHeight += listItem.getMeasuredHeight();  
  11.     }  
  12.   
  13.     ViewGroup.LayoutParams params = listView.getLayoutParams();  
  14.     params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));  
  15.     listView.setLayoutParams(params);  
  16. }  
其实从这段代码中,和上面这个需求,问题已经可以看出来了。

adapter有一个方法getView,这个方法是如果这个listview的某行将要在屏幕上显示了,系统就会自动调用getview得到这个布局,然后显示。

也就是每次被调用的次数,只是屏幕上能显示的条数,最多也就是10条左右。

而一次计算高度就要对每一条调用getview,for循环里面:

[java]   view plain copy
  1. View listItem = listAdapter.getView(i, null, listView);  
[java]   view plain copy
  1. View listItem = listAdapter.getView(i, null, listView);  

是非常耗时的,尤其对于全部城市,几百条,3~4秒肯定是要的。所以面对这个需求,第一种方法是不可行。


除了耗时,第一种方法,维护性也不好。就比如,一个页面中,listview的数据是不定的,是动态计算得到的。用第一种方法分散到多个listview,对于一些事件监听,不好操作。


下面讲解下第二种方法的具体实现

拿上面城市列表具体

分两块:

1、数据dataList

2、adapter

1、datalist填充:

主要以一个flag标记,对于城市列表共有两种布局:

一个是头信息



一个是具体的城市


代码:

[java]   view plain copy
  1. cityList.clear();  
  2.       Map<String, Object> map1 = new HashMap<String, Object>();  
  3.       map1.put("city"new City(0"热门城市"'#'));  
  4.       cityList.add(map1);  
  5.   
  6.       List<City> cities = getHotCity();  
  7.   
  8.       for (City city : cities) {  
  9.           Map<String, Object> map = new HashMap<String, Object>();  
  10.           map.put("is_selected"false);  
  11.           map.put("city", city);  
  12.           cityList.add(map);  
  13.       }  
  14.   
  15.       Map<String, Object> map2 = new HashMap<String, Object>();  
  16.       map2.put("city"new City(0"全部城市"'$'));  
  17.       cityList.add(map2);  
  18.   
  19.       index++;  
  20.       cities = getAllCity();  
  21.   
  22.       for (City city : cities) {  
  23.           Map<String, Object> map = new HashMap<String, Object>();  
  24.           map.put("is_selected"false);  
  25.           map.put("city", city);  
  26.           cityList.add(map);  
  27.       }  
[java]   view plain copy
  1. cityList.clear();  
  2.       Map<String, Object> map1 = new HashMap<String, Object>();  
  3.       map1.put("city"new City(0"热门城市"'#'));  
  4.       cityList.add(map1);  
  5.   
  6.       List<City> cities = getHotCity();  
  7.   
  8.       for (City city : cities) {  
  9.           Map<String, Object> map = new HashMap<String, Object>();  
  10.           map.put("is_selected"false);  
  11.           map.put("city", city);  
  12.           cityList.add(map);  
  13.       }  
  14.   
  15.       Map<String, Object> map2 = new HashMap<String, Object>();  
  16.       map2.put("city"new City(0"全部城市"'$'));  
  17.       cityList.add(map2);  
  18.   
  19.       index++;  
  20.       cities = getAllCity();  
  21.   
  22.       for (City city : cities) {  
  23.           Map<String, Object> map = new HashMap<String, Object>();  
  24.           map.put("is_selected"false);  
  25.           map.put("city", city);  
  26.           cityList.add(map);  
  27.       }  

哦~这个好像没用到flag标记,直接判断city的name了~~~

2、adapter适配:

[java]   view plain copy
  1. @Override  
  2.     public View getView(final int position, View convertView, ViewGroup parent) {  
  3.         City city = (City) listData.get(position).get("city");  
  4.         String nameString = city.getName();  
  5.         if (nameString.compareTo("热门城市") == 0) {  
  6.             convertView = mInflater.inflate(headResource, null);  
  7.             ((TextView) convertView.findViewById(R.id.label)).setText("热门城市");  
  8.             return convertView;  
  9.         }  
  10.         if (nameString.compareTo("全部城市") == 0) {  
  11.             convertView = mInflater.inflate(headResource, null);  
  12.             ((TextView) convertView.findViewById(R.id.label)).setText("全部城市");  
  13.             return convertView;  
  14.         }  
  15.   
  16.         convertView = mInflater.inflate(listResource, null);  
  17.         ((TextView) convertView.findViewById(R.id.label)).setText(nameString);  
  18.         ImageView isSelectedImageView = (ImageView) convertView.findViewById(R.id.is_selected);  
  19.   
  20. //        boolean isSelected = (Boolean) listData.get(position).get("is_selected");  
  21.   
  22.         int whichIsSelected = (Integer) listData.get(getCount() - 1).get("which_is_selected");  
  23.   
  24.         if (city.getId() == whichIsSelected)  
  25.             isSelectedImageView.setBackgroundResource(R.drawable.is_selected_yes);  
  26.         else  
  27.             isSelectedImageView.setBackgroundResource(R.drawable.is_selected_no);  
  28.   
  29.         return convertView;  
  30.     }  
[java]   view plain copy
  1. @Override  
  2.     public View getView(final int position, View convertView, ViewGroup parent) {  
  3.         City city = (City) listData.get(position).get("city");  
  4.         String nameString = city.getName();  
  5.         if (nameString.compareTo("热门城市") == 0) {  
  6.             convertView = mInflater.inflate(headResource, null);  
  7.             ((TextView) convertView.findViewById(R.id.label)).setText("热门城市");  
  8.             return convertView;  
  9.         }  
  10.         if (nameString.compareTo("全部城市") == 0) {  
  11.             convertView = mInflater.inflate(headResource, null);  
  12.             ((TextView) convertView.findViewById(R.id.label)).setText("全部城市");  
  13.             return convertView;  
  14.         }  
  15.   
  16.         convertView = mInflater.inflate(listResource, null);  
  17.         ((TextView) convertView.findViewById(R.id.label)).setText(nameString);  
  18.         ImageView isSelectedImageView = (ImageView) convertView.findViewById(R.id.is_selected);  
  19.   
  20. //        boolean isSelected = (Boolean) listData.get(position).get("is_selected");  
  21.   
  22.         int whichIsSelected = (Integer) listData.get(getCount() - 1).get("which_is_selected");  
  23.   
  24.         if (city.getId() == whichIsSelected)  
  25.             isSelectedImageView.setBackgroundResource(R.drawable.is_selected_yes);  
  26.         else  
  27.             isSelectedImageView.setBackgroundResource(R.drawable.is_selected_no);  
  28.   
  29.         return convertView;  
  30.     }  

对于各行的点击操作也可以根据flag统一处理。维护起来非常方便。
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值