上一篇:Android9编程六:图像资源
一 ConstraintLayout
ConstraintLayout还是非常新的东西。但是的确好用,是Android极力推荐的一个排版控件。
所有叫“Layout”的控件都是用于排版的,就是它能决定它所包含的子控件的位置。这些Layout控件有个特点:可以包含多个子控件。不同的Layout控件,它们排列子控件的方式不一样。ConstraintLayout是既好用又强大的一个,能够应付复杂的要求,而且运行效率很高,一些由多个简单Layout组合实现的界面,应该改由一个ConstraintLayout来实现,当然它也不是万能的。
我们现在的界面就是采用了ConstraintLayout,见下图:
实际上你创建一个新的Activity时,它的layout文件默认就使用ConstraintLayout排版。
二 ConstraintLayout的原理
Constraint是“约束”的意思,我们可以为ConstraintLayout的子控件添加约束,什么约束呢? 位置上的约束。你的App要面对的设备,屏幕有大有小,有方有圆,有宽有窄,要想设计一套界面来适应不同的屏幕就非常难。比如你不可能用固定距离的方式来保持一个控件在横向上居中。有了ConstraintLayout就可以克服这种困难,你可以为一个控件添加一个“保持横向居中”的约束,于是它就横向居中了,不论在任何屏幕上。
可以设置什么样的约束呢? 跟你想要的差不多,比如你可以这样设置控件之间的位置关系:
- 设置子控件左边或右边与ConstraintLayout的左边或右边对齐,这样就可以保持子控件居左或居右。
- 设置子控件下边或上边与ConstraintLayout的上边或下边对齐,以子保持子控件居上或居下。
- 设置子控件在ConstraintLayout中横向居中还是纵向居中还是横向纵向都居中。
- 设置子控件在ConstraintLayout中居中偏左或偏右或偏上或偏下。
- 设置同属于一个ConstraintLayout的子控件A在子控件B的上面或下面或左边或右边。
- 设置同属于一个ConstraintLayout的子控件A与子控件B左边对齐或右边对齐或上边对齐或下边对齐。
你还可以设置子控件本身的约束,比如:
- 宽和高保持n:m的比率。
- 宽或高为某个固定的值。
- 宽或高由内容决定,比如文本控件的大小由文本中文字的个数决定,图像控件的大小由图像的实际大小决定。
下面,让我们把约束的各种姿式都体验一下。
三 子控件在ConstraintLayout中居左或居右
当前的页面中,TextView控件已经居中了。我们把它删掉,用ImageView来搞一下。删除一个控件很简单,选中它,点鼠标右键,在出现的菜单中点“Delete”,也可以选中它直接按“Delete”键。但是,有时可能因为种种原因,不好选中它,那么你可以在控件树中选中它,如下:
删掉它之后,只剩下图像了。现在选中图像。现在未给图像控件加任何约束,于是它默认就在左上角。我们可以为图像添加靠左的限制,但这样其实没效果,那么我们就为它添加靠右的限制吧。见下图:
当鼠标进入控件范围内,就会出现一个边框,这个边框的四个边的中间都有一个小圈圈,当鼠标进入这个圈圈时,它会变大变绿,此时你就可以从这个小圈圈中拖出一条线。这条线就代表了约束。我要靠右,所以我把这条线往Layout控件的右边界拖,当拖到右边界时,图像的边框竟然动了!虽然很诡异,但是你不要惊慌,只需松手即可,出现如下效果:
图像右边到Layout右边的约束已被添加。注意在属性栏中也可以看到约束。属性栏中被矩形框起来的代表了Layout的边,被圆形框起来的代表了一个约束。“8”这个值表示两个控件的边之间的空白的距离。它其实是图像控件的“layout_marginRight”属性,如下图:
现在运行App看看,是不是靠右了? 真的很简单又好玩!怎样让图像靠下呢? 我就不讲了,你自己想吧,以你的智慧肯定能做到,我看好你哦。
四 子控件在ConstraintLayout中横向居中
其实很简单,我只要在上面的基础在再添加一个靠左的约束就行了,如下图:
看到这个效果你是不是感觉很直观? Constraint就像弹簧,如果左右都有弹簧拉它并且左右受力相等的话,它就位于中央了。
上下居中我就不用再讲了吧?我相信以看官你的机智肯定能搞出来。
五 子控件在ConstraintLayout中居中偏左
现在图像左右居中了,但是我们还不满足,我希望它居中再偏左一点,最好在4分之1处居中而不是在2分之1处居中,这样没问题,这就用到这个东西:
它中间有个值“50”表示了左右两个约束的力量,现在是50:50,拖动它试试吧。比如我拖到了25的位置上,如下:
你可以把这个值理解成左右弹簧的力量对比,哪边力大,就偏向哪边。但是,你是否发现一个问题,纵向上没有这个东西。其实是有的,当你在纵向上增加约束之后,它就现身了。
六 子控件A在子控件B的上面
为了演示两个控件之间的相对位置约束,我们需要再添加一个新的控件,就添加一个按钮吧,我们最终让按钮位于图像的上面。但在此之前,我需要为图像控件添加纵向的约束,我先让它横向纵向都居中:
下面再拖一个按钮进来:
拖进来后,这个按钮由于没有约束,所以会跑到左上角去。下面我们为它添加约束。要想让它在图象的上面,那么就从按钮的下边界拖约束到图像的上边界,如下图:
七 子控件A与子控件B左边对齐
上一节的页面中,按钮在横向上没有约束,所以它默认靠左了,看着不舒服,我们让按钮的左边与图像的左边对齐吧:
可以看到两条优美的曲线揭示了约束的存在。不过,仔细看的话,会发现按钮的左边与图像的左边还有一点差距,满没有完全对齐,这其实是按钮的margin在起作用,你要把它的左margin改为0dp,如下:
八 设置子控件的宽和高
以图像控件为例,当前其宽和高为固定值,在属性栏中可以看出来:
注意红线框出的图形,这个样子就表示固定值,值是多少呢? 下面的“layout_width”和“layout_height”的值就是。当你在红框中的图形上点一下鼠标时,会发现图形发生了变化:
图形变成了弹簧的样子,这表示宽度变成了弹性值,即宽度是可变的,同时可以看到layout_width的值变成了“0dp”,此时只要两边没其它控件来挤占它的空间,它就会充满整个空件,此时在预览图中可以看到图像的宽度充满了整个父控件:
九 子控件的宽和高保持一定比例
我们把图像控件搞成宽高按2比1固定吧。
为了更容易看出效果,我们给图像控件设置一下背景。设置背景就是设置控件的background属性。可为设置一种颜色,也可以设置一个图像。先选中图像控件,再在属性栏中点下图所示的按钮:
出现资源选择对话框,选择一种颜色即可:
设置背景后,再来搞一下图像控件的宽高比。还是先选中图像控件,然后在属性栏中点红色箭头所指的位置:
于是在下面的红框位置出现了叫做ratio(比率)的输入控件,可以看到默认是1比1,现在预览图中出现效果:
可以看到图像的宽度收回来了,与高度保持了1:1,注意此时的layout_width和layout_height,对它们的值是有一定要求的,比如如果这这两个值全都不是0dp,那么比率就不起作用了,这里面其实是个优选级的问题,就是有了冲突谁优先起作用。所以要使比例起作用,宽和高必须有一个为0dp,而另一个不能为0dp,可以为match_parent,可以为wrap_content,也可以是大于0dp的固定的值。让我们改成2:1,表示宽是2,高是1,出现效果:
实际上由于图像太宽,已超出了显示区,我们把高度改小一些,比如改成100dp,效果如图:
搞了这么多,layout文件的源码变成什么样了呢? 下面就是:
<?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"
tools:context="niuedu.com.andfirststep.MainActivity">
<ImageView
android:id="@+id/imageView2"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:adjustViewBounds="false"
android:background="@android:color/holo_blue_bright"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="w,2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.498"
app:srcCompat="@drawable/female" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/imageView2"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="@+id/imageView2" />
</android.support.constraint.ConstraintLayout>
(摘自《Android9编程通俗演义》-清华大学出版社,京东淘宝及各大书店有售)