Android ListView的header footer设置visibility gone不起作用

  常用的ViewGroup,例如LinearLayout,在onMeasure方法内对每个child view执行measure前,会判断child view的visibility是否为gone。如果是gone,则不对这个child view执行measure操作,即这个child view的高度不被计算在linearLayout的高度里面。LinearLayout的measureVertical代码片段:

if (child.getVisibility() == View.GONE) {
    i += getChildrenSkipCount(child, i);
    continue;
}

  

  view在measure自己时,并不会去判断自己的Visibility是GONE。这个逻辑操作如上述代码所示,是在parent view里面做的。所以当对LinearLayout里面的一个childView设置Visiblility为gone时,这个view不会被measure,最终也不会被显示出来。

  在使用ListView时,经常会添加一些headerView、footerView。但是当设置headerView、footerView的visibility为gone时,却发现headerView、footerView虽然没有显示出来,但垂直方向其所占的位置还是被显示出来了,从而出现了空白区域。网上查到的解决办法是:不能直接设置headerView、footerView的Visibility为gone。而是要在HeaderView、FooterView外面包一层parent view(FrameLayout RelativeLayout 都可以),并设置layout_height=“wrap_content”。然后对里面的childView设置visibility为GONE、VISIBLE都会生效。查看源码,情况确实如此。

  ListView的onMeasure里面,如果ListView的widthMode、heightMode有一个是unspecified时(应该对应于在XML中没有对listView设置layout_width、layout_height),会调用方法measureScrapChild。如果没有unspecified的情况,则会调用measureHeightOfChildren方法,而此方法内部也会调用measureScrapChild方法。查看measureScrapChild方法:

private void measureScrapChild(View child, int position, int widthMeasureSpec) {
    LayoutParams p = (LayoutParams) child.getLayoutParams();
    if (p == null) {
        p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
        child.setLayoutParams(p);
    }
    p.viewType = mAdapter.getItemViewType(position);
    p.forceAdd = true;

    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,
            mListPadding.left + mListPadding.right, p.width);
    int lpHeight = p.height;
    int childHeightSpec;
    if (lpHeight > 0) {
        childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
    } else {
        childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    }
    child.measure(childWidthSpec, childHeightSpec);
}

  可以看出,listview在对child view执行measure前,没有判断visibility为gone的情况

  再看看里面的详细逻辑:

  • lpHeight>0时,说明在xml或者程序里面设置了一个确定的尺寸,这里没有问题;
  • else里面,设置mode为UNSPECIFIED,就是让child view自己去决定大小,child view在measure自己时,不会考虑VISIBILITY属性。

  else包含的逻辑:

  • lpHeight == 0:对应于在xml或者代码中设置尺寸为0,说明也是不起作用的,最终还是会显示出空白
  • lpHeight == -1:MATCH_PARENT
  • lpHeight == -2:WRAP_CONTENT

  三种情况,都会根据view实际的内容返回一个wrap_content的尺寸。这里就解释了为何设置headerView、footerView的visibility为gone时,会出现空白区域。

  如果外面包一层parent view(例如LinearLayout),并设置layout_height为wrap_content(按上面的分析,设置match_parent也是可以的),listView会调用调用额外的这个parent view的measure方法。而LinearLayout在measure时,会判断child view的visibility,如果为gone,则会返回0.最终这个额外的parent view返回给list view的尺寸就是0,从而解决了空白区域的问题。

  这个问题算是listview的一个feature吧!

时间: 2024-10-10 01:14:14

Android ListView的header footer设置visibility gone不起作用的相关文章

delphi xe6 android ListView增加 Header或Footer 的方法

var  Item1: TListViewItem;begin    Item1 := ListView1.Items.Add;    Item1.Purpose:=TListItemPurpose.Header;//    Item1.Purpose:=TListItemPurpose.Footer;    Item1.text:=' xxxx';//Header或Footer显示的内容end; delphi xe6 android ListView增加 Header或Footer 的方法,布

[Android Bug] ListView中Header, Footer无法隐藏(gone)的问题

ListView中Header.Footer View应该是会应该遇到, 比如说,滚动到底部时,自动开始加载: 对于一些应用市场,会在Header中加上ViewFlipper做应用推荐(滚动的那种,好像很不少市场都有这个功能). 添加时一般大家都会做如下处理: [java] view plaincopyprint? ListView listView = xxxx; listView.addHearderView(item_head); listView.setAdapter(adapter);

Android ListView的item背景色设置

1.如何改变item的背景色和按下颜色 listview默认情况下,item的背景色是黑色,在用户点击时是黄色的.如果需要修改为自定义的背景颜色,一般情况下有三种方法: 1)设置listSelector 2)在布局文件中设置item的background 3)在adapter的getview中设置 这三种方法都能达到改变item默认的背景色和按下颜色,下面来分别讲解,但是在这之前需要先写好selector.xml文件; <?xml version="1.0" encoding=&

求代码:android listview checkbox 从数据库里读取数据后怎么设置相应的checkbox为选中状态

============问题描述============ 现在有一个android listview 带checkbox,从数据库里调取相应数据后,绑定到listview 上. 那么怎么将listview 里的checkbox的选择状态与在数据库中记录一一对应? 求给出代码. 我在自定义BaseAdapter类中,getView方法中无法实现. ============解决方案1============ 这样 你点击的时候 是不是 会获取一个view  通过这个view 获取你那个 checkb

Android ListView,GridView,ScrollView,ProgressBar,SeekBar,RelativeLayout,EditText常用属性

ListView的一些特殊属性: 1.ListView的XML属性 [java] view plaincopy android:divider//在列表条目之间显示的drawable或color android:dividerHeight//用来指定divider的高度 android:entries//构成ListView的数组资源的引用.对于某些固定的资源,这个属性提供了比在程序中添加资源更加简便的方式 android:footerDividersEnabled//当设为false时,Lis

android ListView 分析(一)

需要了解的内容 1. listview中的getItemAtPosition与Adapter的getItem的position的区别 listView中的getItemAtPosition的源码实现: 1 /** 2 * Gets the data associated with the specified position in the list. 3 * 4 * @param position Which data to get 5 * @return The data associated

Android ListView分页,动态添加数据

1.ListView分页的实现,重点在于实现OnScrollListener接口,判断滑动到最后一项时,是否还有数据可以加载, 我们可以利用listView.addFootView(View v)方法进行提示 自定义一个ListView(这里本来想进行一些自定已修改的...实际代码并没有做)CornerListView package com.example.testlistview; import android.widget.AbsListView; import android.conte

Android listview addHeaderView 和 addFooterView 详解

addHeaderView()方法:主要是向listView的头部添加布局 addFooterView()方法:主要是向listView的底部添加布局 需要注意的是添加布局的时候应该添加从父容器开始添加,而不能直接添加父容器中的子控件.例如:从一个xml布局文件中添加一个button控件, 只能将整个布局xml文件添加进去.而不能单单只添加button控件. 当添加头部和底部布局还有另外一个重载方法就是addHeaderView(headView, null, false) 和addFooter

android listview addHeaderView和addFooterView的注意事项

1. item内如果有button等控件时,在监听listview的onitemclick事件时,焦点会被item内的button. imagebutton等控件抢走,从而导致在listview设置了onitemclick事件后不会被触发.解决方法是在初始化item的时候屏蔽掉 其内部button等控件的焦点获取,具体方法可以在自定义item的根控件中调用: [java] view plaincopy setDescendantFocusability(ViewGroup.FOCUS_BLOCK