• 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适配后的高度:

        public static void setListViewHeightBasedOnChildren(ListView listView) {
            ListAdapter listAdapter = listView.getAdapter();
            if (listAdapter == null) {
                return;
            }
            int totalHeight = 0;
            for (int i = 0; i < listAdapter.getCount(); i++) {
                View listItem = listAdapter.getView(i, null, listView);
                listItem.measure(0, 0);
                totalHeight += listItem.getMeasuredHeight();
            }
    
            ViewGroup.LayoutParams params = listView.getLayoutParams();
            params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
            listView.setLayoutParams(params);
        }

    其实从这段代码中,和上面这个需求,问题已经可以看出来了。

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

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

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

    View listItem = listAdapter.getView(i, null, listView);

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

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

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

    拿上面城市列表具体

    分两块:

    1、数据dataList

    2、adapter

    1、datalist填充:

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

    一个是头信息

    一个是具体的城市

    代码:

            cityList.clear();
            Map<String, Object> map1 = new HashMap<String, Object>();
            map1.put("city", new City(0, "热门城市", '#'));
            cityList.add(map1);
    
            List<City> cities = getHotCity();
    
            for (City city : cities) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("is_selected", false);
                map.put("city", city);
                cityList.add(map);
            }
    
            Map<String, Object> map2 = new HashMap<String, Object>();
            map2.put("city", new City(0, "全部城市", '$'));
            cityList.add(map2);
    
            index++;
            cities = getAllCity();
    
            for (City city : cities) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("is_selected", false);
                map.put("city", city);
                cityList.add(map);
            }


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

    2、adapter适配:

    @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            City city = (City) listData.get(position).get("city");
            String nameString = city.getName();
            if (nameString.compareTo("热门城市") == 0) {
                convertView = mInflater.inflate(headResource, null);
                ((TextView) convertView.findViewById(R.id.label)).setText("热门城市");
                return convertView;
            }
            if (nameString.compareTo("全部城市") == 0) {
                convertView = mInflater.inflate(headResource, null);
                ((TextView) convertView.findViewById(R.id.label)).setText("全部城市");
                return convertView;
            }
    
            convertView = mInflater.inflate(listResource, null);
            ((TextView) convertView.findViewById(R.id.label)).setText(nameString);
            ImageView isSelectedImageView = (ImageView) convertView.findViewById(R.id.is_selected);
    
    //        boolean isSelected = (Boolean) listData.get(position).get("is_selected");
    
            int whichIsSelected = (Integer) listData.get(getCount() - 1).get("which_is_selected");
    
            if (city.getId() == whichIsSelected)
                isSelectedImageView.setBackgroundResource(R.drawable.is_selected_yes);
            else
                isSelectedImageView.setBackgroundResource(R.drawable.is_selected_no);
    
            return convertView;
        }

    对于各行的点击操作也可以根据flag统一处理。维护起来非常方便。

  • 相关阅读:
    HTML和XHTML知识总结
    理解margin-left:-100%
    git clean的用法
    vue路由传参的三种基本方式
    vertical-align属性
    纯CSS制作各种图形(多图预警)
    css伪元素:before和:after用法详解
    前端注册登录的业务流程
    Vue-cli 中为单独页面设置背景图片铺满全屏的方法
    vscode 开启对 webpack alias(文件别名) 引入的智能提示
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/5681940.html
Copyright © 2020-2023  润新知