赞
踩
Android推荐使用XML布局文件来定义用户界面,而不是使用Java代码来开发用户界面,因此基础所有组件都提供了两种方式来控制组件的行为:1、在XML布局文件中通过XML属性进行控制;2、在Java程序代码中通过调用方法进行控制;完全使用Java代码来控制UI界面不仅繁琐、而且不利于解耦;而完全利用XML布局文件来控制UI界面虽然方便、便捷,但难免有失灵活。
在编译XML布局文件时,都需要通过main函数中的 onCreate 来调用,通常使用如下方式来进行调用。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_linear_layout);
}
其中setContentView
里的内容‘R’
为就是系统给声明的静态变量,所有的子类都是通过‘R’
来调用。而‘R’
的路径则是 Android 工程路径下的 app -> src -> main -> res
下。
R.layout
指res
文件夹下一个名为layout
的文件夹,而R.layout.activity_linear_layout
之后的部分则是layout
文件夹下自己定义的.xml
文件。
常用的布局方式,
线性布局:LinearLayout
条件布局:ConstraintLayout
相对布局:RelativeLayout
一、线性布局LinearLayout最常用的属性有:
代码如下:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="第一个文本框" android:background="#ffff00"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="第二个文本框" android:background="#ff0000"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="第三个文本框" android:background="#008000"/> </LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="第一个文本框" android:background="#ffff00"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="第二个文本框" android:background="#ff0000"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="第三个文本框" android:background="#008000"/> </LinearLayout>
在这之前先简要说明下match_parent
,fill_parent
和wrap_content
。
match_parent和fill_parent
在效果上相同,都是使该组件的宽度或高度填满父元素,也就是说令其宽度或高度与父元素的宽度或高度一致。回到正题,weight,这里理解为权重,或是比例,需要注意的是:
android:layout_weight="1"
通过设置控件的layout_weight
属性以控制各个控件在布局中的相对大小,线性布局会根据该控件layout_weight值与其所处布局中所有控件layout_weight值之和的比值为该控件分配占用的区域。先看一个例子(以水平布局举例):
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="第一个文本框" android:layout_weight="1" android:background="#ffff00"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="第二个文本框" android:layout_weight="1" android:background="#ff0000"/> <TextView android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:text="第三个文本框" android:layout_weight="1" android:background="#008000"/> </LinearLayout>
还是之前水平布局的例子,只是我们给每个TextView添加了一句android:layout_weight=“1”
貌似达到了我们的预期,三个TextView按1:1:1分完了总宽度。
但有时候可能无法达到预期的效果,请看下面的例子,将三个TextView的android:layout_weight
依次设置为'1','2','3'
:
可以看出三个文本框的大小不一致了,但是明显没有达到我们预期的1:2:3的效果。
这是因为我们设置的每个TextView的宽度为wrap_content
,每个组件都有本身由text内容决定的宽度,只是将剩余的在宽度上的空间按比例分好后再加在其本身的宽度上。
所以说,为达到真正的比例效果:
水平布局时,将每个组件的宽度(width)设置为0dp
竖直布局时,将每个组件的高度(height)设置为0dp
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:gravity="center" android:text="第一个文本框" android:layout_weight="1" android:background="#ffff00"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:gravity="center" android:text="第二个文本框" android:layout_weight="2" android:background="#ff0000"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:gravity="center" android:text="第三个文本框" android:layout_weight="3" android:background="#008000"/> </LinearLayout>
(1)文字没有对齐如何解决?
<?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="horizontal"> <TextView android:layout_width="0dp" android:layout_height="45dp" android:layout_weight="1" android:background="#55ff0000" android:gravity="center" android:text="aaaaaaaaaaaaaaaa"/> <TextView android:layout_width="0dp" android:layout_height="45dp" android:layout_weight="1" android:background="#5500ff00" android:gravity="center" android:text="b"/> <TextView android:layout_width="0dp" android:layout_height="45dp" android:layout_weight="1" android:background="#550000ff" android:gravity="center" android:text="c"/> </LinearLayout>
很明显,第一个textview
的对齐方式不是我们想要的,出现这种现象的原因是LinearLayout默认子控件按照基准线对齐,所以我们需要在
LinearLayout`中添加一个属性就即可解决:android:baselineAligned=“false” 使得子控件不按照基线对齐。
(3)weightSum属性得使用
如果布局中只有一个控件,并且我只想让它占据1/2的宽度,这个时候就可以利用LinearLayout的weightSum属性,来看看这个例子:
<?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="horizontal" android:weightSum="2"> <TextView android:layout_width="0dp" android:layout_height="45dp" android:layout_weight="1" android:background="#55ff0000" android:gravity="center" android:text="aaaaaaaaaaaaaaaa"/> </LinearLayout>
相对布局:相对布局也是常用的布局之一,它可以设置某一个控件相对于其他控件的位置,这些位置可以包括上下左右等,因此相较于其他的布局方式而言具有很大的灵活性。
1.核心属性图
2.父容器定位属性示意图
3.根据兄弟组件定位
恩,先说下什么是兄弟组件吧,所谓的兄弟组件就是处于同一层次容器的组件,如图
图中的组件1,2就是兄弟组件
了,而组件3与组件1或组件2并不是兄弟组件
,所以组件3不能通过 组件1或2来进行定位,比如layout_toleftof = "组件1"这样是会报错的!切记! 关于这个兄弟组件定位的最经典例子就是"梅花布局"了,下面代码实现下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/RelativeLayout1" android:layout_width="match_parent" android:layout_height="match_parent" > <!-- 这个是在容器中央的 --> <ImageView android:id="@+id/img1" android:layout_width="80dp" android:layout_height="80dp" android:layout_centerInParent="true" android:src="@drawable/pic1"/> <!-- 在中间图片的左边 --> <ImageView android:id="@+id/img2" android:layout_width="80dp" android:layout_height="80dp" android:layout_toLeftOf="@id/img1" android:layout_centerVertical="true" android:src="@drawable/pic2"/> <!-- 在中间图片的右边 --> <ImageView android:id="@+id/img3" android:layout_width="80dp" android:layout_height="80dp" android:layout_toRightOf="@id/img1" android:layout_centerVertical="true" android:src="@drawable/pic3"/> <!-- 在中间图片的上面--> <ImageView android:id="@+id/img4" android:layout_width="80dp" android:layout_height="80dp" android:layout_above="@id/img1" android:layout_centerHorizontal="true" android:src="@drawable/pic4"/> <!-- 在中间图片的下面 --> <ImageView android:id="@+id/img5" android:layout_width="80dp" android:layout_height="80dp" android:layout_below="@id/img1" android:layout_centerHorizontal="true" android:src="@drawable/pic5"/> </RelativeLayout>
相对布局常用的属性:
第一类:属性值为true或false:相对于父元素的位置
android:layout_centerHrizontal 水平居中
android:layout_centerVertical 垂直居中
android:layout_centerInparent 相对于父元素完全居中
android:layout_alignParentBottom 贴紧父元素的下边缘
android:layout_alignParentLeft 贴紧父元素的左边缘
android:layout_alignParentRight 贴紧父元素的右边缘
android:layout_alignParentTop 贴紧父元素的上边缘
android:layout_alignWithParentIfMissing 如果对应的兄弟元素找不到的话就以父元素做参照物
实例:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<TextView
android:id="@+id/middle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@android:color/holo_blue_bright"
android:text="我在最中间"/>
</RelativeLayout>
第二类:属性值必须为id的引用名“@id/id-name”,
//相对于子元素外部的位置
android:layout_below 在某元素的下方
android:layout_above 在某元素的的上方
android:layout_toLeftOf 在某元素的左边
android:layout_toRightOf 在某元素的右边
//相对于子元素内部的位置
android:layout_alignTop 本元素的上边缘和某元素的的上边缘对齐
android:layout_alignLeft 本元素的左边缘和某元素的的左边缘对齐
android:layout_alignBottom 本元素的下边缘和某元素的的下边缘对齐
android:layout_alignRight 本元素的右边缘和某元素的的右边缘对齐
实例:相对于元素外部四周
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <TextView android:id="@+id/middle" android:layout_width="200dp" android:layout_height="200dp" android:gravity="center" android:layout_centerInParent="true" android:background="@android:color/holo_blue_bright" android:text="我在最中间"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/middle" android:text="layout_below" android:layout_centerHorizontal="true" android:background="@android:color/holo_green_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@id/middle" android:text="layout_above" android:layout_centerHorizontal="true" android:background="@android:color/holo_green_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/middle" android:text="layout_toLeftOf" android:layout_centerVertical="true" android:background="@android:color/holo_green_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/middle" android:text="layout_toRightOf" android:layout_centerVertical="true" android:background="@android:color/holo_green_light"/> </RelativeLayout>
实例:相对于元素内部四周
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white"> <TextView android:id="@+id/middle" android:layout_width="200dp" android:layout_height="200dp" android:gravity="center" android:layout_centerInParent="true" android:background="@android:color/holo_blue_bright" android:text="我在最中间"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@id/middle" android:text="layout_alignBottom" android:layout_centerHorizontal="true" android:background="@android:color/holo_orange_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/middle" android:text="layout_alignTop" android:layout_centerHorizontal="true" android:background="@android:color/holo_orange_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@id/middle" android:text="alignLeft" android:layout_centerVertical="true" android:background="@android:color/holo_orange_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignRight="@id/middle" android:text="alignRight" android:layout_centerVertical="true" android:background="@android:color/holo_orange_light"/> </RelativeLayout>
第三类:属性值为具体的像素值,如30dip,40px
android:layout_marginBottom 离某元素底边缘的距离
android:layout_marginLeft 离某元素左边缘的距离
android:layout_marginRight 离某元素右边缘的距离
android:layout_marginTop 离某元素上边缘的距离
android:gravity
android:layout_gravity
Margin:设置组件与父容器(通常是布局)的边距
android:layout_margin: 指定控件的四周的外部留出一定的边距
android:layout_marginLeft: 指定控件的左边的外部留出一定的边距
android:layout_marginTop: 指定控件的上边的外部留出一定的边距
android:layout_marginRight: 指定控件的右边的外部留出一定的边距
android:layout_marginBottom: 指定控件的下边的外部留出一定的边距
Padding:设置组件内部元素间的边距(可以理解为填充)
android:padding :指定控件的四周的内部留出一定的边距
android:paddingLeft: 指定控件的左边的内部留出一定的边距
android:paddingTop: 指定控件的上边的内部留出一定的边距
android:paddingRight: 指定控件的右边的内部留出一定的边距
android:paddingBottom: 指定控件的下边的内部留出一定的边距
android:layout_margin就是设置view的上下左右边框的额外空间
android:padding是设置内容相对view的边框的距离
padding,含义为“填充”,像垫肩压类似的填充物,一个控件的padding及此控件内部的填充,由此可见padding是以所被定义的控件A为parent控件,而内部的内容物与控件A的间距。而layout_margin是A控件所在的控件为parent控件,是A与其的间距。
其实概念很简单,padding是站在父view的角度描述问题,它规定它里面的内容必须与这个父view边界的距离。margin则是站在自己的角度描述问题,规定自己和其他(上下左右)的view之间的距离,如果同一级只有一个view,那么它的效果基本上就和padding一样了
当按钮分别设置以上两个属性时,得到的效果是不一样的。
android:paddingLeft="30px"
按钮上设置的内容(例如图片)离按钮左边边界30个像素
android:layout_marginLeft="30px"
整个按钮离左边设置的内容30个像素
使用示例
1、两个都不加
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" >
<TextView
android:layout_width="100dip"
android:layout_height="100dip"
android:background="#000000"
android:text="Hello" />
</RelativeLayout>
2、只加padding
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding ="100dip"
android:background="#ffffff" >
<TextView
android:layout_width="100dip"
android:layout_height="100dip"
android:background="#000000"
android:text="Hello" />
</RelativeLayout>
3、只加margin
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff" >
<TextView
android:layout_width="100dip"
android:layout_height="100dip"
android:background="#000000"
android:layout_margin="30dip"
android:text="Hello" />
</RelativeLayout>
注意说明
在LinearLayout、RelativeLayout、TableLayout中,这2个属性都是设置都是有效的
在FrameLayout中,android:layout_margin是无效的,因为FrameLayout里面的元素都是从左上角开始绘制的
在AbsoluteLayout中,没有android:layout_margin属性
在此提醒,xml参数中含有layout的参数项目为定义的控件相对于parent的关联,没有的一般为本身的定义,以上内容与此相符。又类似于gravity跟layout_gravity,带layout的是相对于parent的大体位置,而不带的是自身内部内容的大体位置。
在以前,android是使用布局如LinearLayout 、RelativeLayout等来构建页面,但这些布局使用起来很麻烦,并且经常需要一层一层嵌套,写一个简单的页面就需要费很大的劲。
1、较高的性能优势。
2、完美的屏幕适配
3、书写简单
4、可视化编辑。
api 'com.android.support.constraint:constraint-layout:1.1.2'
属性 | 描述 |
---|---|
app:layout_constraintLeft_toLeftOf | 把A的left side放在B的left side(左边对齐) |
app:layout_constraintLeft_toRightOf | 把A的left side放在B的right side(左边相对右边对齐) |
app:layout_constraintRight_toLeftOf | 把A的right side放在B的left side(右边相对左边对齐) |
app:layout_constraintRight_toRightOf | 把A的right side放在B的right side(右边对齐) |
app:layout_constraintTop_toTopOf | 把A的top side放在B的top side(顶部对齐) |
app:layout_constraintTop_toBottomOf | 把A的top side放在B的bottom side(顶部相对底部对齐) |
app:layout_constraintBottom_toTopOf | 把A的bottom side放在B的top side(底部相对顶部对齐) |
app:layout_constraintBottom_toBottomOf | 把A的bottom side放在B的bottom side(底部对齐) |
app:layout_constraintStart_toEndOf | 把A的start position放在B的end position(起始位置相对结束位置对齐) |
app:layout_constraintStart_toStartOf | 把A的start position放在B的start position(起始位置对齐) |
app:layout_constraintEnd_toStartOf | 把A的end position放在B的start position(结束位置相对起始位置对齐) |
app:layout_constraintEnd_toEndOf | 把A的end position放在B的end position(结束位置对齐) |
app:layout_constraintBaseline_toBaselineOf | 把A的bottom side放在B的top side(基准线对齐) |
来看个例子:
<android.support.constraint.ConstraintLayout ...> <Button android:id="@+id/a" .... app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="A" /> <Button android:id="@+id/b" .... app:layout_constraintLeft_toRightOf="@id/a" app:layout_constraintTop_toTopOf="@id/a" android:text="B" /> <Button android:id="@+id/c" .... app:layout_constraintLeft_toLeftOf="@id/a" app:layout_constraintTop_toBottomOf="@id/a" android:text="C" /> <Button android:id="@+id/d" .... app:layout_constraintLeft_toRightOf="@id/a" app:layout_constraintTop_toTopOf="@id/c" android:text="D" /> </android.support.constraint.ConstraintLayout>
从中可以看到,
1、layout_constraint*属性的值可以是某个id或者parent(父布局)
2、B要位于A的右边,则使用app:layout_constraintLeft_toRightOf="@id/a",C位于A的下边,则使用app:layout_constraintTop_toBottomOf="@id/a"
对于一个View的边界界定,官方给了下面这张图:
在约束布局中,margin控制需要存在约束关系的才会生效,比如控件A某条边相对于控件B的某条边存在约束关系,则控件A与B之间的margin才会生效。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.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:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/right_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/color_1" android:gravity="center" android:text="右上角" app:layout_goneMarginStart="20dp" android:layout_marginStart="20dp" android:textSize="32sp" android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_min="120dp" /> <TextView android:id="@+id/where" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我在哪里" app:layout_goneMarginEnd="20dp" android:layout_marginEnd="20dp" android:background="#ff0000" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toLeftOf="@+id/right_top"/> </androidx.constraintlayout.widget.ConstraintLayout>
这里使用了两种margin属性,一种就是app:layout_goneMarginEnd,这个只在right_top被gone的时候生效;一种就是android:layout_marginEnd,任何时候都生效。
但是这里的margin需要生效,只有id为where的TextView被id为right_top的TextView所约束,那么id为where的TextView的margin相对于id为right_top的TextView的才生效。而id为right_top的TextView并没有被id为where的TextView约束,所以id为right_top的TextView的margin_start其实看不到生效。这里其实可以认为right_top的margin_start生效了,只不过是相对于parent的左边,但是因为right_top在parent的右上角,所以看不到这个margin效果
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout ...> <Button android:id="@+id/a" ... android:layout_marginLeft="100dp" android:layout_marginTop="20dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/b" ... android:layout_marginLeft="20dp" android:layout_marginTop="20dp" app:layout_constraintLeft_toRightOf="@id/a" app:layout_constraintTop_toTopOf="@id/a" /> <Button android:id="@+id/c" .... android:layout_marginLeft="20dp" android:layout_marginTop="20dp" app:layout_constraintLeft_toRightOf="@id/b" app:layout_constraintTop_toTopOf="@id/b" /> </android.support.constraint.ConstraintLayout>
考虑一个问题,如果B动态设为gone了,C会怎么显示呢?
真实情况如下:
为什么会这样显示呢?看他的蓝图应该会好理解些:
可以看出,b设为gone之后,他的宽、高、margin都失效了,变为一个点了,但它的constrain还生效,位于指定的位置。c还是可以继续以他为锚点。
那么如何解决关于View gone引起的非预期的布局变化呢?
一个view如何设置为居中呢?如果查找属性,会发现并没有如RelativeLayout类似的layout_centerVertical属性,那如何设置居中呢?constraint的思想很巧妙。
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
根据第一节的知识,大家知道如果设置app:layout_constraintLeft_toLeftOf=“parent”,则view会贴着父view的左边,设置app:layout_constraintRight_toRightOf=“parent” 则会贴着右边,那如果两个都设置,效果会怎样呢?
如图,两个都设置,view则会居中。
如果是在两个控件的中间,则可以:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.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:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/left_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/color_3" android:gravity="center" android:text="左上角" android:textSize="32sp" app:layout_constraintStart_toStartOf="@id/root" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_min="120dp" /> <TextView android:id="@+id/right_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/color_1" android:gravity="center" android:text="右上角" app:layout_goneMarginStart="20dp" android:layout_marginStart="20dp" android:textSize="32sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_min="120dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我在哪里" android:background="#ff0000" app:layout_constraintLeft_toRightOf="@+id/left_top" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toLeftOf="@+id/right_top"/> </androidx.constraintlayout.widget.ConstraintLayout>
至此可以看出,对constraint的理解其实可以看成是像两个弹簧一样,如果只在左边加一个弹簧,右边没有,那左边的势必会把view拉到左边去,如果在右边也加一根弹簧,两个弹簧力相互平衡,则view就居中了。
上面是view居中,如果我想让view向左偏一些,或者位于1/3处该怎么处理?其实也是一样的,想象一下,如果左边的弹簧力大一些,view不是就自然往左偏了嘛。如何使力大一些呢?使用如下属性
这两个属性单独使用并不能生效,水平方向的必须要给控件的左右两边都添加约束才会生效,垂直方向的必须要给控件的上下两边都添加约束才可以生效。
bias即偏移量,他们的取值范围从0~1,0即挨着左边,1是挨着右边,所以要使处于1/3处,可以设置如下属性app:layout_constraintHorizontal_bias=“0.33”,效果图如下:
实例:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.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:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" app:layout_constraintHorizontal_bias="0.4" app:layout_constraintVertical_bias="0" app:layout_constraintLeft_toRightOf="@+id/left_top" app:layout_constraintRight_toRightOf="parent" tools:layout_editor_absoluteX="120dp" tools:layout_editor_absoluteY="189dp" /> <TextView android:id="@+id/left_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/color_3" android:gravity="center" android:text="左上角" android:textSize="32sp" app:layout_constraintStart_toStartOf="@id/root" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_min="120dp" /> </androidx.constraintlayout.widget.ConstraintLayout>
比如这个例子,Button的左边被TextView的右边约束,Button的右边被parent约束,这样Button的左右两边都有约束,那么给Button添加水平方向的bias属性就可以生效,即根据Button的左边约束偏移一定的比例,这里就是相对于TextView的右边位置偏移40%。
bias的偏移,是根据控件的水平或者垂直方向的剩余位置的百分比来偏移。
设置view的大小除了传统的wrap_content、指定尺寸、match_parent(虽然官方不推荐使用match_parent)外,还可以设置为0dp(官方取名叫MATCH_CONSTRAINT),0dp在constraint可不是指大小是0dp,而是有特殊含义的。他的作用会随着不同的设置有不同的含义:
layout_constraintWidth_default,有三个取值,作用如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
...>
<Button
android:id="@+id/a"
android:layout_width="0dp"
...
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
</android.support.constraint.ConstraintLayout>
可以看到layout_width为0dp,实际的效果则是宽度和约束一样,左右两边的留白是margin的效果。
2、percent,意思是按照父布局的百分比设置,需要layout_constraintWidth_percent设置百分比例
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout > <android.support.constraint.ConstraintLayout android:layout_width="300dp" android:layout_height="400dp" app:layout_constraintHorizontal_bias="0.3" > <Button android:id="@+id/a" android:layout_width="0dp" ... app:layout_constraintRight_toRightOf="parent" app:layout_constraintWidth_default="percent" app:layout_constraintWidth_percent="0.4" /> </android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
A的宽度设为0.4,则其宽度为父布局的0.4倍。另外,设置了layout_constraintWidth_percent属性,可以不用指定layout_constraintWidth_default,他会自动设置为percent
3、wrap,意思匹配内容大小但不超过约束限制,注意和直接指定宽度为wrap_content的区别就是不超过约束限制,如下
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout ...> <Button android:id="@+id/a" ... app:layout_constraintLeft_toLeftOf="parent" /> <Button android:id="@+id/c" ... app:layout_constraintRight_toRightOf="parent" /> <Button android:id="@+id/b" android:layout_width="0dp" ... app:layout_constraintWidth_default="wrap" app:layout_constraintLeft_toRightOf="@id/a" app:layout_constraintRight_toLeftOf="@id/c"/> <Button android:id="@+id/d" android:layout_width="wrap_content" ... app:layout_constraintTop_toBottomOf="@id/b" app:layout_constraintLeft_toRightOf="@id/a" app:layout_constraintRight_toLeftOf="@id/c"/> </android.support.constraint.ConstraintLayout>
可以看到虽然文字很长,但第一行的绿色button宽度达到约束时,就不在增加,而第二行的button显示了完整的内容,超过约束的限制。
ratio
layout_constraintDimensionRatio,即宽和高成一定的比例,其值可以是"width:height"的形式,也可以是width/height的值。该属性生效的前提:宽和高其中有一项为0dp,有constraint。下面按照有几个0dp来分别介绍下:
max min
有如下属性可以设置其的最大最小值,含义如字面值一样:
layout_constraintWidth_min
layout_constraintWidth_max
layout_constraintHeight_max
layout_constraintHeight_min
在ConstraintLayout中给控件设置min的宽度和高度,必须是要控件的layout_width或者layout_height为wrap_content或者0dp时。给控件设置max的宽度或者高度的时候,必须是要控件的layout_width或者layout_height为0dp时。
不过在设置max的时候需要注意一点,如果单纯只是设置了0dp,如果没给控件添加对应的左右约束或者上下约束,比如没有设置左右约束,那么layout_constraintWidth_max设置的再大也不会超过整个控件的wrap_content的长度。
这里的绿色区域的控件,宽度显示的明显没有达到550dp,但是也不会继续变长了。
如果是设置了左右约束,那么最大宽度的限制也就是左右两个约束中间的剩余空间宽度
1. GuideLine
即参考线的意思,有水平参考线和竖直参考线两种。他的作用就像是一个虚拟的参考线,只是用来方便其他View以他为锚点来布局。
如上一篇所了解到的,ConstraintLayout 的定位原则就是一个View参考其他View的相对布局,如果有的时候当前布局没有合适的参考View,而建一个专门用于定位的View又会太重,这种情况正是GuideLine的用武之地。
例如:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout ...> <android.support.constraint.Guideline android:id="@+id/guideline" ... android:orientation="vertical" app:layout_constraintGuide_percent="0.33" /> <android.support.constraint.Guideline android:id="@+id/guideline2" ... android:orientation="horizontal" app:layout_constraintGuide_begin="130dp" /> <Button ... app:layout_constraintLeft_toLeftOf="@id/guideline" app:layout_constraintTop_toTopOf="@id/guideline2" /> </android.support.constraint.ConstraintLayout>
可以看到我分别添加了一个水平参考线和竖直参考线,之后的Button的布局就参考与这两个参考线,而在布局中并不会显示。
Guideline的大部分的属性如layout_width都是不会生效的,而他的位置的确定是由下面三个属性之一来确定的:
2. Barrier
屏障,一个虚拟View。他主要解决下面遇到的问题:
如上图布局,两个TextView,一个button位于他们的右边。现在button设置的是在下面TextView的右边。假设有时候上面的TextView文本变长了,则布局会变为下面这个样子:
上面的TextView和Button重叠了。这时该怎么解决这个问题呢?Button只能设置一个View作为锚点,设置了上面就顾不了下面了。。。
所以就诞生了Barrier,他可以设置N个View作为锚点,使用方式如下:
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"//end,left,right,top,bottom
app:constraint_referenced_ids="text1,text2" />
则Barrier始终位于text1,text2两个View最大宽度的右边,示意图如下:
3.Guideline和Barrier的区别
这两个都是线条,都是辅助约束的,但是这两个有一点区别,就是当控件比如出现切换手机语言,而造成控件上的文本显示长度出现变化的时候,Guideline并不会随着控件的长度变化而变化,这样就会造成约束不灵活,而Barrier可以根据控件的宽高变化,灵活移动位置。
所以控件宽高是随着内容动态变化的,建议使用Barrier,如果控件的内容是不变的,可以使用Guideline。
1、https://www.cnblogs.com/xpwi/p/9690113.html
2、https://blog.csdn.net/hang916/article/details/81809271
3、https://www.jianshu.com/p/e1f65e094b24
4、https://www.cnblogs.com/liter7/p/5178674.html
5、https://www.jianshu.com/p/13dc7ad66eb1
6、https://www.runoob.com/w3cnote/android-tutorial-relativelayout.html
7、https://www.cnblogs.com/angrycode/p/9739513.html
8、https://blog.csdn.net/guolin_blog/article/details/53122387
9、https://www.jianshu.com/p/502127a493fb
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。