前几天,我刚写了一篇批判社会的文章。如今滴滴司机的事件让全国知道这件事儿的人聚拢了起来。其实生活在这种环境下,我们会不得不像生活妥协。用《我不是药神》的一句话就是:“我相信未来一定会更好”。
说在前头
以前在写布局的时候,经常会写出这样的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />w
</LinearLayout>
</RelativeLayout>
</LinearLayout>
复制代码
这种代码本身写法是没有错误的,也能完成业务需求。但是一旦页面复杂起来,这种嵌套很容易造成页面的卡顿。因为查看源码得知,视图的渲染是一层一层渲染的,这种复杂度很高的渲染将会比简单的布局渲染的时间会加长。
在16年I/O大会上,google发布了全新的布局--
ConstraintLayout
。根据官方的解释,这个布局主要有下面三个优点:
- 可以减轻复杂度,让页面性能更好。( 性能优势 )
- 更加友好的适配
- 入手友好
一、 ConstraintLayout基本属性介绍:
1、 基本属性
谈到
ConstraintLayout
,就要从最基本的几个属性来谈谈:
- 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
关于这些属性的名字呢!我就不一一赘述了,大家敲一下代码就晓得了。我就抛砖引玉的先做一个示例吧:
如图:要达成这样的布局,如果按照以前的写法的话,估计需要嵌套个两层,我这里就不多加赘述了,有兴趣的可以自己去写一写。但是用上ConstraintLayout,代码如下:
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/item_text_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/item_text_title_defalt"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/item_text_img"
app:layout_constraintTop_toTopOf="@id/item_text_img" />
<TextView
android:id="@+id/item_text_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/item_text_content_defalt"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="@id/item_text_title"
app:layout_constraintTop_toBottomOf="@id/item_text_title" />
</android.support.constraint.ConstraintLayout>
复制代码
上面的代码,我们可以发现一个布局就可以解决问题。layout_constraint可以依靠于一个基准的id或者是parent来定位。
2、 margin
那张图会比较拥挤,我想带来一个间距,达到这样的效果:
margin
了,代码如下:
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/item_text_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/item_text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/item_text_title_defalt"
android:textSize="20sp"
android:layout_marginStart="10dp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/item_text_img"
app:layout_constraintTop_toTopOf="@id/item_text_img" />
<TextView
android:id="@+id/item_text_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/item_text_content_defalt"
android:layout_marginTop="5dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="@id/item_text_title"
app:layout_constraintTop_toBottomOf="@id/item_text_title" />
</android.support.constraint.ConstraintLayout>
复制代码
首先我们值得注意的是: item_text_img 使用 layout_marginEnd是无效的,不信读者可以试试。并且在使用layout_margin*的时候,一定要确定对应方向的位置,不然也是无效的。
3、 关于view gone
现在有这么一个样式的布局:
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/frist_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffff0000"
android:text="frist"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/second_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="#ffff0000"
android:text="second"
android:textColor="@android:color/white"
app:layout_constraintStart_toEndOf="@id/frist_btn"
app:layout_constraintTop_toBottomOf="@id/frist_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:background="#ffff0000"
android:text="final"
android:textColor="@android:color/white"
app:layout_constraintStart_toEndOf="@id/second_btn"
app:layout_constraintTop_toBottomOf="@id/second_btn" />
</android.support.constraint.ConstraintLayout>
复制代码
如果中间的second的visible为Gone或者是invisible会成如何呢?
当second为gone了之后,我们发现final就会直接继承second的位置关系占领住second的位置。但是当second为invisible了则保留second的位置。所以尽量使用invisible。当然google还是提供了一种方法:
layout_goneMargin
,在一定程度上可以解决这个问题,有兴趣的可以试试这个属性。
4、 居中
关于居中对齐这个事儿了,无论是在写前端和Android端都是一个必须知道的东西,如果了解透了,其实并没有什么的花里胡哨的东西。看下面一段代码:
<?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"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@android:color/darker_gray">
<Button
android:id="@+id/frist_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffff0000"
android:text="frist"
android:textColor="@android:color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</android.support.constraint.ConstraintLayout>
复制代码
效果如下:
但是google官方还给予了一个
bias
属性,如下所示:
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.8"
复制代码
得到的效果图如下:
bias
可以设置权重
由上面的示意图可以知道,当我们确定button的宽度和高度非0之后,再与parent的四周对齐之后。控件会与parent的四周构成一个弹簧,从而将控件拉到居中的位置,为什么说确定控件的宽度和高度呢?来看下面一段代码:
android:layout_width="0dp"
android:layout_height="0dp"
复制代码
效果图如下:
5、 ratio
layout_constraintDimensionRatio:即宽和高成一定的比例,其值可以是"width:height"的形式,也可以是width/height的值。该属性生效的前提:宽和高其中有一项为0,有constraint。代码如下:
android:layout_width="0dp"
android:layout_height="20dp"
app:layout_constraintDimensionRatio="4"
复制代码
效果图如下:
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="4"
复制代码
效果图如下:
如果两项都为0dp,则尺寸会设置为满足约束的最大值并保持比例。相当于该属性失效。
二、 GuideLine基准线介绍:
这个很简单的,看英文名称大概就能猜出来,这个东西就是一个辅助线的意思。众所周知,contractlayout是根据四周的环境分布来确定位置的,有了这个东西就能有很大的裨益。先来看一下它有哪些方法:
- orientation:基准线的方向
- layout_constraintGuide_begin:距离父布局的左边或者上边多大距离
- layout_constraintGuide_end:距离父布局的右边或者下边多大距离
- layout_constraintGuide_percent:百分比,0~1,距离父布局的左边或者上边占父布局的比例 实例代码如下:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray">
<android.support.constraint.Guideline
android:id="@+id/test_guide_line"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="200dp"/>
<Button
android:id="@+id/frist_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="test"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/test_guide_line" />
</android.support.constraint.ConstraintLayout>
复制代码
效果图如下:
三、 Group
有的时候,因为页面的需要经常会需要控制多个view的显示和隐藏,所以官方在
contractlayout1.1
增加了
Group
属性,用来控制多个view的显隐性。
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray">
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="left_btn,right_bot_btn"/>
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="right_btn,left_bot_btn"/>
<Button
android:id="@+id/left_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="left"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/right_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/left_bot_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="left"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<Button
android:id="@+id/right_bot_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right"
android:textColor="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
复制代码
这里要值得注意的是:
- xml中,可见性配置的优先级:Group优先于View,下层Group优先于上层。
- Group只能映射同级layout下的ConstraintLayout下的View,其他级别下的View没有效果。
- constraint_referenced_ids里直接写的是id的字符串,初始化后会通过getIdentifier来反射查找叫该名字的id。所以如果你的项目用了类似AndResGuard的混淆id名字的功能,切记不要混淆app:constraint_referenced_ids里的id,否则在release版本就会因找不到该id而失效。或者也可以通过代码setReferencedIds来设置id(这个是看的别人的😂😂😂)。
四、 Placeholder
这个叫做占位属性,也是我在看别人的文章里面看到的。先看代码: