layout_gravity
Android开发必遇问题,最有可能忘记两者之间的区别的问题之一
如下是Google搜索出来的结果
记忆方法
联想/形像記法
* 利用成员变量的属性记录,gravity是类的成员变量,自然就是控制子节点的排版效果,设置自己内部的排版重心,即排版内部子类的参数。排版它人的重心(主动)
* layout_gravity的前缀有layout,即属于layoutparams类的属性值,然后LayoutParams是给父view用的,即 layout_gravity是设置自己在父view的排版重点,即被排版时的参数!被它人排版的重心(被动)
文档说明
android:gravity
关键字 should position , 主动
android:layout_gravity
关键字 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;
}
相关补充
- ViewGroup是个抽象类,子类继承它时需要Override OnLayout方法
- LinearLayout、relativelayout等ViewGroup子类就分别实现了自己的排版算法(Override OnLayout方法)
- 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);
}
}
}
相关阅读
android线程管理五(ActivityThread与ApplicationThread
前言 android中App第一次启动时,会创建一个进程,在这个进程中可以启动各个组件(如Activity、BroadcastReceiver、Service),这些组件都
一文读懂 android 事件分发机制 MotionEvent
点击事件用MotionEvent表示,最重要的事件分别是: 手指按下:ACTION_DOWN 手指移动:ACTION_MOVE 手指抬起:ACTION_UP 点击事件的分发始
Android入门教程二十五之Button(按钮)与ImageButton(
今天给大家介绍的Android基本控件中的两个按钮控件,Button普通按钮和ImageButton图像按钮; 其实ImageButton和Button的用法基本类似
Android主线程(ActivityThread)源代码分析
在写这篇博客之前,先抛出一个问题,安卓应用程序的入口是什么呢?我想不少人可能回答说:application的onCreate方法,其实并不是的,即使
android 英语词库(未完待续) drawable英 ['drɔ:əbl] 美 ['drɔəbl]adj.可曳的,可拉的; Compound英 [ˈkɒmpaʊnd] 美 [