View有一个方法setVisibility,作用是可以控制视图的显示和隐藏,int类型的参数可以传入三种值View.VISIBLE, View.GONE, View.INVISIBLE,其中VISIBILE表示设置视图显示,GONE和INVISIBLE设置视图隐藏,区别在于前者隐藏后不占用视图空间,而后者隐藏后依然占用视图空间。具体不同看下源码:
/**
* Set the enabled state of this view.
*
* @param visibility One of {@link #VISIBLE} , {@link #INVISIBLE}, or {@link #GONE} .
* @attr ref android.R.styleable#View_visibility
*/
@RemotableViewMethod
public void setVisibility( int visibility) {
// 针对参数VISIBLE, INVISIBLE, GONE三种情况进行处理
setFlags(visibility, VISIBILITY_MASK);
if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
}
从setVisibility方法的源码可以看出,setFlags很关键,下面来看看其源码:
/**
* Set flags controlling behavior of this view.
*
* @param flags Constant indicating the value which should be set
* @param mask Constant indicating the bit range that should be changed
*/
void setFlags( int flags, int mask) {
int old = mViewFlags;
mViewFlags = (mViewFlags & ~mask) | (flags & mask);
int changed = mViewFlags ^ old;
if (changed == 0) {
return;
}
int privateFlags = mPrivateFlags;
......
if ((flags & VISIBILITY_MASK) == VISIBLE) {
if ((changed & VISIBILITY_MASK) != 0) {
/*
* If this view is becoming visible, set the DRAWN flag so that
* the next invalidate() will not be skipped.
*/
mPrivateFlags |= DRAWN ;
needGlobalAttributesUpdate(true);
// a view becoming visible is worth notifying the parent
// about in case nothing has focus. even if this specific view
// isn't focusable, it may contain something that is, so let
// the root view try to give this focus if nothing else does.
if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
mParent.focusableViewAvailable(this);
}
}
}
/* Check if the GONE bit has changed */
if ((changed & GONE) != 0) {
needGlobalAttributesUpdate(false);
// 此处是与INVISIBLE参数的区别,GONE隐藏不占用空间,因为重新布局
requestLayout();
invalidate();
if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
if (hasFocus()) clearFocus();
// 此处是与INVISIBLE参数的区别,销毁绘制缓存
destroyDrawingCache();
}
if (mAttachInfo != null) {
mAttachInfo.mViewVisibilityChanged = true;
}
}
/* Check if the VISIBLE bit has changed */
if ((changed & INVISIBLE) != 0) {
needGlobalAttributesUpdate(false);
invalidate();
if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
// root view becoming invisible shouldn't clear focus
if (getRootView() != this) {
clearFocus();
}
}
if (mAttachInfo != null) {
mAttachInfo.mViewVisibilityChanged = true;
}
}
if ((changed & VISIBILITY_MASK) != 0) {
dispatchVisibilityChanged( this, (flags & VISIBILITY_MASK));
}
......
}