您的位置:首页 > 移动开发 > Android开发

Android多版本兼容一(FrameLayout布局兼容)

2015-09-28 17:46 393 查看
          给大家介绍下本人开发过程中遇到的Android多版本兼容的一些坑,只是针对Android的api的一些算是缺陷,引起开发中一些界面的问题,此贴会持续更新。

        开发中假如你使用FrameLayout包含子视图,假如没有定义子View的gravity,同时定义了子View的margin,那么你就中招了,你会发现子View的margin在4.0以上的系统显示正常,而在Android2.3的系统中没起到作用。我们一起走下Android的framework这块的api,来看下这块的版本差异:

        细心的你可能很快就会定位到FrameLayout的onLayout方法,一起来看下Android版本的差异:

        这是Android2.3.2的源码:

@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 LayoutParams lp = (LayoutParams) child.getLayoutParams();

final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();

int childLeft = parentLeft;
int childTop = parentTop;

final int gravity = lp.gravity;

if (gravity != -1) {
final int horizontalGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;

switch (horizontalGravity) {
case Gravity.LEFT:
childLeft = parentLeft + lp.leftMargin;
break;
case Gravity.CENTER_HORIZONTAL:
childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
lp.leftMargin - lp.rightMargin;
break;
case Gravity.RIGHT:
childLeft = parentRight - width - lp.rightMargin;
break;
default:
childLeft = parentLeft + lp.leftMargin;
}

switch (verticalGravity) {
case Gravity.TOP:
childTop = parentTop + lp.topMargin;
break;
case Gravity.CENTER_VERTICAL:
childTop = parentTop + (parentBottom - parentTop - height) / 2 +
lp.topMargin - lp.bottomMargin;
break;
case Gravity.BOTTOM:
childTop = parentBottom - height - lp.bottomMargin;
break;
default:
childTop = parentTop + lp.topMargin;
}
}

child.layout(childLeft, childTop, childLeft + width, childTop + height);
}
}
}
        可以看出layout_gravity没有解析到有效的数值,childLeft和childTop不会解析子view的margin,直接进行了layout。

        这是Android4.0的源码:

@Override
protected void More 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) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();

final int width = child.getMeasuredWidth();
final int height = child.getMeasuredHeight();

int childLeft;
int childTop;

int gravity = lp.gravity;
if (gravity == -1) {
gravity = DEFAULT_CHILD_GRAVITY;
}

final int layoutDirection = getResolvedLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;

switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.LEFT:
childLeft = parentLeft + lp.leftMargin;
break;
case Gravity.CENTER_HORIZONTAL:
childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
lp.leftMargin - lp.rightMargin;
break;
case Gravity.RIGHT:
childLeft = parentRight - width - lp.rightMargin;
break;
default:
childLeft = parentLeft + lp.leftMargin;
}

switch (verticalGravity) {
case Gravity.TOP:
childTop = parentTop + lp.topMargin;
break;
case Gravity.CENTER_VERTICAL:
childTop = parentTop + (parentBottom - parentTop - height) / 2 +
lp.topMargin - lp.bottomMargin;
break;
case Gravity.BOTTOM:
childTop = parentBottom - height - lp.bottomMargin;
break;
default:
childTop = parentTop + lp.topMargin;
}

child.layout(childLeft, childTop, childLeft + width, childTop + height);
}
}
}
        可以看到Android4.0的FrameLayout在onLayout中修复了2.3的问题,针对于默认的layout_gravity就认为是Gravity.LEFT | Gravity.TOP,对子view进行layout。

        那么解决方案就是针对FrameLayout的布局,需要用到margin,需要在子view设置默认的layout_gravity:Gravity.LEFT | Gravity.TOP。

        好的,这一期就到这,谢谢各位看客,有问题可以和我们沟通。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息