android:layout_gravity 和 android:gravity 的区别

Android开发必遇问题,最有可能忘记两者之间的区别的问题之一
如下是Google搜索出来的结果
android:layout_gravity 和 android:gravity 的区别_第1张图片

记忆方法

联想/形像記法
* 利用成员变量的属性记录,gravity是类的成员变量,自然就是控制子节点的排版效果,设置自己内部的排版重心,即排版内部子类的参数。排版它人的重心(主动)
* layout_gravity的前缀有layout,即属于LayoutParams类的属性值,然后LayoutParams是给父view用的,即 layout_gravity是设置自己在父view的排版重点,即被排版时的参数!被它人排版的重心(被动)

文档说明

android:gravity

android:layout_gravity 和 android:gravity 的区别_第2张图片
关键字 should position , 主动

android:layout_gravity

android:layout_gravity 和 android:gravity 的区别_第3张图片
关键字 should be placed, 被动

源码左证

如下是LinearLayout的onLayout函数中可以看到两个参数的使用情况

 void layoutVertical(int left, int top, int right, int bottom) {
        final int paddingLeft = mPaddingLeft;

        int childTop;
        int childLeft;

        // Where right end of child should go
        final int width = right - left;
        int childRight = width - mPaddingRight;

        // Space available for child
        int childSpace = width - paddingLeft - mPaddingRight;

        final int count = getVirtualChildCount();

        final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
        final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
        // 使用mGravity来计算第一个子view的top
        switch (majorGravity) {
           case Gravity.BOTTOM:
               // mTotalLength contains the padding already
               childTop = mPaddingTop + bottom - top - mTotalLength;
               break;

               // mTotalLength contains the padding already
           case Gravity.CENTER_VERTICAL:
               childTop = mPaddingTop + (bottom - top - mTotalLength) / 2;
               break;

           case Gravity.TOP:
           default:
               childTop = mPaddingTop;
               break;
        }

        for (int i = 0; i < count; i++) {
            final View child = getVirtualChildAt(i);
            if (child == null) {
                childTop += measureNullChild(i);
            } else if (child.getVisibility() != GONE) {
                final int childWidth = child.getMeasuredWidth();
                final int childHeight = child.getMeasuredHeight();
                //在排子view时才使用到子view的LayoutParams中的gravity
                final LinearLayout.LayoutParams lp =
                        (LinearLayout.LayoutParams) child.getLayoutParams();

                int gravity = lp.gravity;
                if (gravity < 0) {
                    gravity = minorGravity;
                }

相关补充

  1. ViewGroup是个抽象类,子类继承它时需要Override OnLayout方法
  2. LinearLayout、RelativeLayout等ViewGroup子类就分别实现了自己的排版算法(Override OnLayout方法)
  3. ViewGroup子类们在排版过程中使用到gravity与layout_gravity等参数来排版子view(内容),值得注意的是mGravity不是ViewGroup的成员变量,另外各子类的排版策略是不一样的,所以gravity不是必须存在的与使用的,如FrameLayout
    如下是FrameLayout的OnLayout方法的代码
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        layoutChildren(left, top, right, bottom, false /* no force left gravity */);
    }

    void layoutChildren(int left, int top, int right, int bottom,
                                  boolean forceLeftGravity) {
        final int count = getChildCount();

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

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

        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 = getLayoutDirection();
                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;

                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                    case Gravity.CENTER_HORIZONTAL:
                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
                        lp.leftMargin - lp.rightMargin;
                        break;
                    case Gravity.RIGHT:
                        if (!forceLeftGravity) {
                            childLeft = parentRight - width - lp.rightMargin;
                            break;
                        }
                    case Gravity.LEFT:
                    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);
            }
        }
    }

你可能感兴趣的:(Java,ANDROID,Android开发之旅,android)