在4.0以下系统中FrameLayout设置margin失效

在4.0以下 使用FrameLayout时会发现在给子view设置了margin之后,发现没有起到作用

主要原因

在API 4.0以下系统,FrameLayout 中子View设置margin值时必须和layout_gravity一起使用,否则margin将不起作用

原因分析

主要是由于不同版本中,FrameLayoutonLayout中排布子View存在差异
对比一下 2.3 和 4.0 我们可以发现问题所在

  • API 2.3
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int count = getChildCount();

        final int parentLeft = mPaddingLeft + mForegroundPaddingLeft;
        final int parentRight = right - left - mPaddingRight - mForegroundPaddingRight;

        final int parentTop = mPaddingTop + mForegroundPaddingTop;
        final int parentBottom = bottom - top - mPaddingBottom - mForegroundPaddingBottom;

        mForegroundBoundsChanged = true;
        
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
               //...
               //...

                final int gravity = lp.gravity;

                if (gravity != -1) {
                  //...
                  //...
                }

                child.layout(childLeft, childTop, childLeft + width, childTop + height);
            }
        }
    }
  • API 4.0
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        final int count = getChildCount();

        final int parentLeft = getPaddingLeftWithForeground();
        final int parentRight = right - left - getPaddingRightWithForeground();

        final int parentTop = getPaddingTopWithForeground();
        final int parentBottom = bottom - top - getPaddingBottomWithForeground();

        mForegroundBoundsChanged = true;
        
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                //...
                //...
                int gravity = lp.gravity;
                if (gravity == -1) {
                    gravity = DEFAULT_CHILD_GRAVITY;
                }

                //...
                //...

                child.layout(childLeft, childTop, childLeft + width, childTop + height);
            }
        }
    }

可以看到主要区别在于
API 2.3是判断gravity == -1则不使用子布局的margin
API 4.0是判断gravity == -1则使用默认的gravity DEFAULT_CHILD_GRAVITY

源码中可以看到定义的 DEFAULT_CHILD_GRAVITY

private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.LEFT;

为什么会比较gravity == -1
因为在 FrameLayoutLayoutParams中可以看到gravity的默认值就是-1

public LayoutParams(Context c, AttributeSet attrs) {
    super(c, attrs);

    TypedArray a = c.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout_Layout);
    gravity = a.getInt(com.android.internal.R.styleable.FrameLayout_Layout_layout_gravity, -1);
    a.recycle();
}

所以在4.0一下使用FrameLayout 是 子View 设置margin的时候一定要和layout_gravity一起使用

你可能感兴趣的:(在4.0以下系统中FrameLayout设置margin失效)