前几天,我刚写了一篇批判社会的文章。如今滴滴司机的事件让全国知道这件事儿的人聚拢了起来。其实生活在这种环境下,我们会不得不像生活妥协。用《我不是药神》的一句话就是:“我相信未来一定会更好”。
说在前头
以前在写布局的时候,经常会写出这样的布局:
<?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"
效果图如下:
由上图可以知道:若有一项为0dp,另一项不为0时。则该项值按照比例计算出来。比如高为20dp,宽为0dp,radio为"4",则最终宽为80dp
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
这个叫做占位属性,也是我在看别人的文章里面看到的。先看代码:
<?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="match_parent"
android:background="@android:color/darker_gray">
<Button
android:id="@+id/place_holder_btn"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right"
android:textColor="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<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" />
<android.support.constraint.Placeholder
android:id="@+id/place_holder"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#ffff0000"
android:text="right"
app:content="@+id/place_holder_btn"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</android.support.constraint.ConstraintLayout>
效果图如下:
这个布局存在的效果就是占位符,当content指向另外一个组件的时候,组件本身会gone掉,然后装载到placeholder的位置。(我还没摸透这个存在的意义)
五、 Barrier
关于这个属性,直接来看代码比较好理解一点:
<?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="match_parent"
android:background="@android:color/darker_gray">
<Button
android:id="@+id/frist_btn"
android:layout_width="20dp"
android:layout_height="50dp"
android:layout_marginTop="20dp"
android:background="#ffff0000"
android:textColor="@android:color/white"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/second_btn"
android:layout_width="20dp"
android:layout_height="50dp"
android:layout_marginStart="40dp"
android:layout_marginTop="40dp"
android:background="#76ea0a"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="frist_btn,second_btn"/>
<Button
android:id="@+id/final_btn"
android:layout_width="20dp"
android:layout_height="50dp"
android:background="#0a24ea"
android:layout_marginStart="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/barrier"
/>
</android.support.constraint.ConstraintLayout>
效果图如下:
我想由上面的代码,应该晓得了Barrier的作用。我的理解就是这是一个虚拟的view,跟guideline一样辅助view定位的。
但是当红色的布局gone的时候回发生什么呢?
这里呢?我也是看一篇文章里面这么说的,此时需要添加这么个属性:
app:barrierAllowsGoneWidgets="false"
效果图如下:
就不用管第一个view的显隐性了,直接去对齐第二个选项了。
当然Barrier
这个是我看别人写的文档看来的,暂时还没有在项目中使用,后续会在里面多多使用这些新的特性的。
说在最后
首先说一下为什么要写这篇文章,第一是:大学同学在问我Android相关的知识;第二是:自己也想在接下来的时间里面多总结一点Android方面的知识。毕竟做Android这么久了。也不是说转前端就不管了。无论怎么说 还是希望Android和前端两匹马拉着我向大佬层次迈进的。
不知不觉我从开始写文章以来已经过去了6个月了,其实相对于以前能力并没有显著的提高。并且还花费着我很多的时间(运行、总结的时间),但是我还是一如既往的坚持了下来。我期待着厚积薄发、期待着傻人有傻福的一天😂😂😂
共同学习,写下你的评论
评论加载中...
作者其他优质文章