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中头布局的效果
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ccc"
android:orientation="horizontal">
<TextView
android:layout_marginLeft="10dp"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="title测试"/>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="250dp"
android:src="@drawable/ic_launcher_foreground" />
<ImageView
android:layout_marginLeft="10dp"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/ic_launcher_foreground" />
</LinearLayout>
实现效果:
android:layout_marginLeft="10dp" 这个属性是根据上一个控件的位置计算偏移
案例二:实现每个在布局中均分的效果
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ccc"
android:orientation="horizontal">
<TextView
android:gravity="center"
android:layout_gravity="center_vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="title测试"/>
<ImageView
android:layout_height="30dp"
android:layout_width="0dp"
android:layout_weight="1"
android:src="@drawable/ic_launcher_foreground" />
<ImageView
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/ic_launcher_foreground" />
</LinearLayout>
实现效果:
结论: 首先明确一个概念,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布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ccc">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:text="测试title" />
<ImageView
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" />
<ImageView
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" />
</RelativeLayout>
实现效果:
如果想根据图片上端对齐,只需设置 android:layout_alignTop="@id/iv_test1"
效果如图:
案例二:做一个中间一个大控件、四周小空间控件分别对齐大控件的上下左右四个方向
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#678"
android:layout_toLeftOf="@+id/rl_big"
android:layout_alignTop="@id/rl_big"
>
</RelativeLayout>
<RelativeLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#123"
android:layout_toRightOf="@+id/rl_big"
android:layout_alignBottom="@+id/rl_big"
>
</RelativeLayout>
<RelativeLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#886"
android:layout_above="@id/rl_big"
android:layout_alignRight="@id/rl_big"
>
</RelativeLayout>
<RelativeLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#886"
android:layout_below="@+id/rl_big"
android:layout_alignLeft="@id/rl_big"
>
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl_big"
android:layout_width="160dp"
android:layout_height="160dp"
android:background="#ccc"
android:layout_centerInParent="true"></RelativeLayout>
</RelativeLayout>
效果图:
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.support.constraint.Group
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.support.constraint.Guideline
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
效果完美 代码如下
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
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.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#666">
<TextView
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" />
<ImageView
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" />
<ImageView
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.support.constraint.ConstraintLayout>
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.66" />
<android.support.constraint.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="41dp" />
<FrameLayout
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">
<TextView
android:layout_width="327dp"
android:layout_height="45dp"
android:gravity="center"
android:textColor="@color/txt_selector"
android:text="ViewPager" />
</FrameLayout>
<android.support.constraint.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="143dp" />
<android.support.constraint.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.3561644" />
<TextView
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.support.constraint.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.33" />
<android.support.constraint.Guideline
android:id="@+id/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<android.support.constraint.Guideline
android:id="@+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.65" />
<TextView
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" />
<TextView
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" />
<TextView
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" />
<TextView
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" />
<TextView
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" />
<TextView
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.support.constraint.Guideline
android:id="@+id/guideline9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_end="50dp" />
<RadioGroup
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">
<RadioButton
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="学习" />
<RadioButton
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="社区" />
<RadioButton
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="消息" />
<RadioButton
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="我的牛客" />
</RadioGroup>
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="#b5f5f4"
android:text="我是随便填充的内容"
app:layout_constraintBottom_toTopOf="@+id/rgp_bottom_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline8" />
</android.support.constraint.ConstraintLayout>
几乎没有嵌套,用起来非常爽。