Common ViewGroup, such as LinearLayout, determine whether the visibility of child view is gone before performing measure on each child view within the Onmeasure method. If it is gone, the measure operation is not performed on this child view, that is, the height of the child view is not computed at the height of the linearlayout. LinearLayout's measurevertical code snippet:
if (child.getvisibility () = = View.gone) {+ = Getchildrenskipcount (child, I ); Continue ;}
View in measure himself, and will not judge their own visibility is gone. This logical operation, as shown in the preceding code, is done in the parent view. So when a childview in LinearLayout is set visiblility to gone, the view will not be measure and will not be displayed.
When using the ListView, some Headerview, Footerview are often added. But when set Headerview, Footerview visibility for gone, but found that Headerview, footerview although not shown, but the vertical direction of its occupied position is displayed, resulting in a blank area. Online Find the solution is: can not directly set Headerview, Footerview visibility for gone. Instead, wrap a layer of parent view (Framelayout relativelayout) outside of Headerview, Footerview, and set layout_height= "Wrap_content". Then the inside of the Childview set visibility for gone, visible will take effect. Look at the source code, that's exactly the case.
Onmeasure inside the ListView, if the ListView Widthmode, Heightmode has a unspecified (should correspond to the ListView in the XML is not set Layout_width, Layout_height), Method Measurescrapchildis called. If there is no unspecified, the Measureheightofchildren method is called, and the Measurescrapchild method is called inside this method. To view the Measurescrapchild method:
Private voidMeasurescrapchild (View Child,intPositionintWidthmeasurespec) {Layoutparams P=(Layoutparams) child.getlayoutparams (); if(p = =NULL) {p=(Abslistview.layoutparams) generatedefaultlayoutparams (); Child.setlayoutparams (P); } P.viewtype=Madapter.getitemviewtype (position); P.forceadd=true; intChildwidthspec =Viewgroup.getchildmeasurespec (Widthmeasurespec, Mlistpadding.left+mlistpadding.right, P.width); intLpheight =P.height; intChildheightspec; if(Lpheight > 0) {Childheightspec=Measurespec.makemeasurespec (Lpheight, measurespec.exactly); } Else{Childheightspec= Measurespec.makemeasurespec (0, measurespec.unspecified); } child.measure (Childwidthspec, Childheightspec);}
It can be seen that theListView did not judge visibility as gone before executing measure on the child view .
Then look at the detailed logic inside:
- lpheight>0 , the description in the XML or program inside set a certain size, there is no problem;
- else inside, set mode to unspecified, is to let the child view herself to determine the size, child view in measure themselves, do not consider the visibility attribute.
else contains the logic:
- Lpheight = = 0: Corresponds to setting the size of 0 in XML or code, the description is also not working, and eventually will show a blank
- Lpheight = = -1:match_parent
- Lpheight = = -2:wrap_content
In three cases, a wrap_content size will be returned based on the actual content of the view. This explains why a blank area appears when you set Headerview, Footerview visibility to gone.
If you are wrapping a layer of parent view (for example, LinearLayout), and set Layout_height to Wrap_content (as shown in the above analysis, it is possible to set match_parent), The ListView invokes the measure method that calls the additional parent view. And LinearLayout in measure, will judge the child view visibility, if it is gone, will return 0. Finally, the extra parent view returns to the list view with a size of 0, which solves the problem with the blank area.
This question is a feature of the ListView!
Android ListView Header Footer Set visibility gone does not work