在4.0以下 使用FrameLayout
时会发现在给子view
设置了margin
之后,发现没有起到作用
主要原因
在API 4.0以下系统,FrameLayout
中子View
设置margin
值时必须和layout_gravity
一起使用,否则margin将不起作用
原因分析
主要是由于不同版本中,FrameLayout
的onLayout
中排布子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
因为在 FrameLayout
的 LayoutParams
中可以看到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
一起使用