Android布局小记
布局系列通用属性
1.android:layout_width="match_parent"
2.android:layout_height="match_parent"
3.android:gravity="" 设置被包裹的空间的位置
4.android:visibility= 显示 visible 不显示,但占空间 invisible 隐藏 gone
5.layout_gravity 设置控件相对于父控件的位置
还有些不怎么很常用的,用的时候再查好了
LinearLayout (线性布局)
LinearLayout 常用在布局嵌套的情况下,控件在布局中可以按照水平或者垂直排列。最好不要设置成wrap_content,这样会导致二次测量(后面源码中有解释)。
特点:控件一定不会出现重叠的情况
基本属性:
1.android:orientation 设置布局的排列方式,水平或者垂直
2.android:layout_weight="1"权值设置,某个控件占布局的多少(linearLayout中控件属性)
注:如果android:orientation设置为horizontal 那么在控件中android:layout_gravity="center_horizontal"无效。(因为布局的排列方式和这种设置时冲突的,举个例子,这就像父母让孩子上学,孩子想去游乐园,结果自然是听父母的)
案例一,利用LinearLayout实现APP中头布局的效果
android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ccc" android:orientation="horizontal"> android:layout_marginLeft="10dp" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="title测试"/> android:layout_width="30dp" android:layout_height="30dp" android:layout_marginLeft="250dp" android:src="@drawable/ic_launcher_foreground" /> android:layout_marginLeft="10dp" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/ic_launcher_foreground" />
实现效果:
android:layout_marginLeft="10dp" 这个属性是根据上一个控件的位置计算偏移
案例二:实现每个在布局中均分的效果
android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ccc" android:orientation="horizontal"> android:gravity="center" android:layout_gravity="center_vertical" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="title测试"/> android:layout_height="30dp" android:layout_width="0dp" android:layout_weight="1" android:src="@drawable/ic_launcher_foreground" /> android:layout_width="0dp" android:layout_height="30dp" android:layout_weight="1" android:src="@drawable/ic_launcher_foreground" />
实现效果:
结论: 首先明确一个概念,LinearLayout常在布局嵌套的外层使用,在上面的例子也能看出,在LinearLayout直接放控件实在写起来麻烦,官方也不赞同这么做。
LinearLayout源码简单分析:
对于一个ViewGroup绘制必走的三个流程,onMeasure,onLayout,onDraw,顺着看一下源码是怎么写的
public class LinearLayout extends ViewGroup {
/** @hide */
@IntDef({HORIZONTAL, VERTICAL})
@Retention(RetentionPolicy.SOURCE)
......
首先LinearLayout是继承ViewGroup的
然后是出现的是四个构造函数
简单记一下:
第一个构造函数:只有在代码中new的时候调用,官网解释也很简单
第二个构造函数:在xml中使用的时候调用,最常用的一种
第三个构造函数:在xml中,LinearLayout布局中控件有设定style属性,就开始调用第三个构造函数,并有得到结论【结论1】:优先级xml定义>style>theme(本行结论参考https://www.jianshu.com/p/7389287c04bb)
第四个构造函数:我试了几种方案都没有调用,但是上面链接也写了那种情况。
第一步: onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mOrientation == VERTICAL) {
measureVertical(widthMeasureSpec, heightMeasureSpec);
} else {
measureHorizontal(widthMeasureSpec, heightMeasureSpec);
}
}
判断了一下LinearLayout的orientation属性,然后根据orientation写了两个方法,追一个看看
-------------------------------measureVertical()方法干了什么------------------------------------
// See how tall everyone is. Also remember max width.
for (int i = 0; i < count; ++i) {
final View child = getVirtualChildAt(i);
.......
//根据注释,这一块是看一下每一个控件的高,然后记住最大的宽度。然后获取权重等等
// 测量模式有三种:
// * UNSPECIFIED:父控件对子控件无约束
// * Exactly:父控件对子控件强约束,子控件永远在父控件边界内,越界则裁剪。如果要记忆的话,可以记忆为有对应的具体数值或者是Match_parent
// * AT_Most:子控件为wrap_content的时候,测量值为AT_MOST。
//这里获取总权重,当我们设置了总权重则用我们设置的权重值,如果没有设置,则用子控件权重相加的和
从这里推出**结论** linearLayout的onMeasure进行了两次测量
结论 : LinearLayout是wrap_content,或者mode为UNSPECIFIED,计算新的mTotalLength,因为这时候所有子控件都是用最大控件的最小值
注:mode为UNSPECIFIED的情况并不常见,LinearLayout 设置的是横向的 但是你的子布局全是充满屏幕 就这点感觉就均分不了的,可能会出现这种情况。
第二步:onMeasure方法。
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mOrientation == VERTICAL) {
layoutVertical(l, t, r, b);
} else {
layoutHorizontal(l, t, r, b);
}
}
这一步也有两个方法
第三步:绘制onDraw()
RelativeLayout(相对布局)
相对布局以前是as中默认布局,每个控件都默认在左上角,需要手动设置控件的之间的位置关系
居中属性:
android:layout_centerHrizontal 水平居中
android:layout_centerVertical 垂直居中
android:layout_centerInparent 相对于父控件完全居中
位置调整属性:
android:layout_alignParentBottom 贴紧父控件的下边缘
android:layout_alignParentLeft 贴紧父控件的左边缘
android:layout_alignParentRight 贴紧父控件的右边缘
android:layout_alignParentTop 贴紧父控件的上边缘
android:layout_below 在某控件下方
adroid:layout_above 在某控件上方
android:layout_toLeftOf 在某控件的左边
android:layout_toRightOf 在某控件的右边
android:layout_alignTop 本控件的上边缘和某控件的上边缘对齐
android:layout_alignLeft 本控件的左边缘和某控件的左边缘对齐
android:layout_alignBottom 本控件的下边缘和某控件的下控件对齐
android:layout_alignRight 本控件的右边缘和某控件的有边缘对齐
案例一:同理实现一个title布局
android:layout_width="match_parent" android:layout_height="50dp" android:background="#ccc"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginLeft="15dp" android:text="测试title" /> android:id="@+id/iv_test1" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="23dp" android:src="@drawable/ic_launcher_foreground" /> android:layout_width="20dp" android:layout_height="20dp" android:layout_marginRight="20dp" android:layout_toLeftOf="@id/iv_test1" android:layout_centerVertical="true" android:src="@drawable/ic_launcher_foreground" />
实现效果:
如果想根据图片上端对齐,只需设置 android:layout_alignTop="@id/iv_test1"
效果如图:
案例二:做一个中间一个大控件、四周小空间控件分别对齐大控件的上下左右四个方向
android:layout_width="match_parent" android:layout_height="match_parent" > android:layout_width="50dp" android:layout_height="50dp" android:background="#678" android:layout_toLeftOf="@+id/rl_big" android:layout_alignTop="@id/rl_big" > android:layout_width="50dp" android:layout_height="50dp" android:background="#123" android:layout_toRightOf="@+id/rl_big" android:layout_alignBottom="@+id/rl_big" > android:layout_width="50dp" android:layout_height="50dp" android:background="#886" android:layout_above="@id/rl_big" android:layout_alignRight="@id/rl_big" > android:layout_width="50dp" android:layout_height="50dp" android:background="#886" android:layout_below="@+id/rl_big" android:layout_alignLeft="@id/rl_big" > android:id="@+id/rl_big" android:layout_width="160dp" android:layout_height="160dp" android:background="#ccc" android:layout_centerInParent="true">
效果图:
ConstraintLayout(限制布局)
RelativeLayout+LinearLayout+x=ConstraintLayout。第一感觉,这个布局好麻烦啊,第二感觉,有点意思,第三感觉,我得好好看看。
可以完全没有嵌套,空间位置完全按照想要的角度去设计 按照牛客网的界面,用ConstraintLayout去实现以下。
属性信息:
在代码中经常有top bottom start end一些确定位置信息,用一张图来解读,
A控件:start是根布局,也就是parent,top也是指向了根布局,也是parent,只看A控件,如果没有别的设置,那么这两个约束会让它出现在左上角
B控件:start是A,top是c,end是根布局也就是parent,只看b控件,那么它出现的位置一定是A控件的右边 c控件的下面,而且是A控件和右边边界的中间。
ConstraintLayout有一个位置确定,那么其他的控件都可以根据这个控件确定好位置,解决了多层嵌套的问题。
常见为的位置设置信息(选取代码中的一段)
1.app:layout_constraintBottom_toTopOf="@+id/guideline8" 简单理解为在某个空间的底部之上,也就是在谁上面 这个是设置某个控件位置在guideline8之上
2.app:layout_constraintEnd_toEndOf="@+id/textView5" 同理 设置结束位置to结束位置,也就是当前控件和textView5的结束位置相同
3.app:layout_constraintStart_toStartOf="@+id/textView5"设置开始位置to开始位置,意味着开始位置相同
4.app:layout_constraintTop_toTopOf="@+id/guideline7"设置顶部位置为guideline7
5.app:layout_constraintHorizontal_bias="0.0" 水平位置百分比 范围0~1之间,0为原点,1为屏幕最右端。还有一个垂直的,同理
这个代码中 2和3 确定了当前控件与textView5垂直居中对齐。
这些就是大同小异了,不用可以记,根据上面的坐标系想想就ok了
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
工具简单介绍
1.group 用组来控制控件,将iv_title,imageView,iv_test2放到一个组里,然后统一控制。一定要注意,这个不是把控件包裹起来(否则报错:java.lang.ClassCastException: android.support.constraint.Group cannot be cast to android.view.ViewGroup)
android:id="@+id/group" android:background="#ff0" android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="iv_title,imageView,iv_test2" /> 2.guildLine 这个帮助布局控件的定位,有两种形式,可以百分比定位也可以dp确认位置,非常灵活 android:id="@+id/guideline8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.65" /> 效果图720*1280 效果图1080*2340 效果完美 代码如下 xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#666"> android:id="@+id/iv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="8dp" android:text="牛客" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> android:id="@+id/imageView" android:layout_width="30dp" android:layout_height="30dp" android:layout_marginEnd="80dp" android:src="@mipmap/ic_pixaloop_question" app:layout_constraintBottom_toBottomOf="@+id/iv_title" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toRightOf="@+id/iv_title" app:layout_constraintTop_toTopOf="@+id/iv_title" app:layout_constraintVertical_bias="0.5" /> android:layout_width="30dp" android:layout_height="30dp" android:layout_marginEnd="20dp" android:src="@mipmap/ic_pixaloop_question" app:layout_constraintBottom_toBottomOf="@+id/imageView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toRightOf="@+id/iv_title" app:layout_constraintTop_toTopOf="@+id/imageView" app:layout_constraintVertical_bias="0.5" /> android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.66" /> android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="41dp" /> android:id="@+id/frameLayout2" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:background="#ccc" app:layout_constraintBottom_toTopOf="@+id/guideline3" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2"> android:layout_width="327dp" android:layout_height="45dp" android:gravity="center" android:textColor="@color/txt_selector" android:text="ViewPager" /> android:id="@+id/guideline3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="143dp" /> android:id="@+id/guideline4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.3561644" /> android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_marginStart="8dp" android:layout_marginTop="5dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="介绍信息" app:layout_constraintBottom_toTopOf="@+id/guideline4" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.483" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline3" /> android:id="@+id/guideline5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.33" /> android:id="@+id/guideline7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.5" /> android:id="@+id/guideline8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.65" /> android:id="@+id/textView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="TextView" app:layout_constraintBottom_toTopOf="@+id/guideline7" app:layout_constraintEnd_toStartOf="@+id/guideline5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline4" app:layout_constraintVertical_bias="0.5" /> android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" app:layout_constraintBottom_toBottomOf="@+id/textView4" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/textView4" /> android:id="@+id/textView6" android:layout_width="wrap_content" android:layout_height="19dp" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:text="TextView" app:layout_constraintBottom_toBottomOf="@+id/textView5" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="@+id/textView5" /> android:id="@+id/textView7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:text="TextView" app:layout_constraintBottom_toTopOf="@+id/guideline8" app:layout_constraintEnd_toEndOf="@+id/textView4" app:layout_constraintStart_toStartOf="@+id/textView4" app:layout_constraintTop_toTopOf="@+id/guideline7" /> android:id="@+id/textView8" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:text="TextView" app:layout_constraintBottom_toTopOf="@+id/guideline8" app:layout_constraintEnd_toEndOf="@+id/textView5" app:layout_constraintStart_toStartOf="@+id/textView5" app:layout_constraintTop_toTopOf="@+id/guideline7" app:layout_constraintVertical_bias="0.514" /> android:id="@+id/textView9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:text="TextView" app:layout_constraintBottom_toTopOf="@+id/guideline8" app:layout_constraintEnd_toEndOf="@+id/textView6" app:layout_constraintStart_toStartOf="@+id/textView6" app:layout_constraintTop_toTopOf="@+id/guideline7" app:layout_constraintVertical_bias="0.512" /> android:id="@+id/guideline9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_end="50dp" /> android:id="@+id/rgp_bottom_menu" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="15dp" android:gravity="center" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline9"> android:id="@+id/rb_study" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:clickable="true" android:textColor="@color/txt_selector" android:drawableTop="@drawable/click" android:gravity="center" android:text="学习" /> android:id="@+id/rb_community" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:textColor="@color/txt_selector" android:drawableTop="@drawable/click" android:gravity="center" android:text="社区" /> android:id="@+id/rb_message" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:textColor="@color/txt_selector" android:drawableTop="@drawable/click" android:gravity="center" android:text="消息" /> android:id="@+id/rb_myNk" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:textColor="@color/txt_selector" android:drawableTop="@drawable/click" android:gravity="center" android:text="我的牛客" /> 几乎没有嵌套,用起来非常爽。