天天记录 - Android setVisibility参数VISIBLE, GONE, INVISIBLE与源码简单分析

      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));
        }
        ......
    }

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/androiddevelop/article/details/8557546
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞