约束布局

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liangjingkanji/article/details/77046764

Constraintlayout

译为”约束布局“, 是Google在AndroidStudio2.2引入的布局. 在AndroidStudio 2.3直接替代了之前的Activity创建的默认布局RelativeLayout. 可以看到Google对其重视性.

特点

  1. 配合布局编辑器,提升效率(鼠标创建布局)
  2. 更好的屏幕适配(百分比适配屏幕和控件)
  3. 解决布局嵌套过多引起的性能问题(只需要一个根布局就能解决)
  4. 添加动画效果更加简单(一行代码添加动画)
  5. 支持代码布局控件(完全不使用XML来画布局)

注意: 本文讲解的ConstraintLayout是在1.0.2正式版的前提下. 这个布局后续肯定是会频繁更新的, 出入是会存在的.

官方文档

布局编辑器

ConstraintLayout的最大特点就是很好的支持AndroidStudio的布局编辑器. 之前的布局其实也支持布局编辑器, 但是效果很差, 所以都使用XML编辑代码.

布局编辑器面板

布局编辑器左边有个面板, 用于拖控件到布局编辑器中

控件列表

在布局编辑器的左边就是全部的控件列表. 可以通过直接拖动到布局预览界面来创建视图控件. 并且不需要你手动导入依赖包.

布局编辑器设置

依次介绍:

  1. 只显示预览
  2. 只显示蓝图
  3. 蓝图和预览都显示
  4. 预览界面显示方向
  5. 手机屏幕型号
  6. 系统API版本
  7. 预览界面主题
  8. 预览界面语言
  9. 布局变形(即详细定制一个预览布局)

预览图和蓝图

顺序依次

预览图主要显示手机的实际效果(ConstraintLayout拥有布局编辑器属性, 所以存在预览界面和实际应用不同的情况), 蓝图主要清晰显示布局的信息

两者都可以直接编辑布局, 看你的喜好.

预览界面控制

  1. 缩小
  2. 缩放百分比
  3. 放大
  4. 适应屏幕
  5. 打开一个缩略图(可以控制预览界面显示范围)
  6. 错误和警告提示数量

ConstraintLayout布局属性

这一栏是根据你选择的ViewGroup变化的布局属性栏, 这里我只介绍ConstraintLayout的布局属性栏, 其他的没什么好介绍的一看就知道了.

依次功能:

  1. 是否显示全部约束(不管是否开启都会显示你选择控件的约束的)
  2. 自动连接约束(AutoConnect)
  3. 删除所有约束
  4. 推论约束(infer Constraint)
  5. 默认边距
  6. 对齐方式
  7. 排列方式
  8. 辅助线(GuideLine)

自动连接约束(AutoConnect)

这个类似磁铁的图标如果处于开启状态. 控件只要一拖到布局编辑器中就会自动创建水平和垂直方向各一条约束.

推论约束(Infer Constraint)

该功能属于一次性功能, 点击一次就会自动计算并且给当前布局编辑器中所有没有进行约束处理的控件进行水平和垂直方向各一条约束.

辅助线(GuidLine)

这个功能其实就相当于PS或者说很多作图工具中的一个辅助线

属性

除了布局编辑器写布局也应该要了解布局的属性, 不然有些问题你看不出来的.

编辑器属性(Editor)

该属性并不会在Android上有任何影响, 只会影响AS的布局编辑器坐标

tools:layout_editor_absoluteY="246dp"
tools:layout_editor_absoluteX="36dp"

布局编辑器

真机上

约束(Constraint)

一个控件有四个约束点/ 十二个约束属性(左和右有各有两个属性start和end以及right和left)

约束只能是同一水平下才能相互约束, 例如左和右之间能约束, 左不能和上下约束点关联.

约束并不是相互关联的关系. 而是

// 和父布局关联约束
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"

// 和其他控件关联约束
app:layout_constraintLeft_toRightOf="@+id/button3"
app:layout_constraintRight_toLeftOf="@+id/button3"
app:layout_constraintTop_toBottomOf="@id/button3"
app:layout_constraintBottom_toTopOf="@id/button3"


layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

文字基准线(BaseLine)

有些控件是包含文字内容的, 所以约束布局的控件有一个文字基准线约束. 默认是隐藏,需要点击开关显示.

layout_constraintBaseline_toBaselineOf

注意: 使用了文字基准线对齐就不需要使用上下约束了

百分比偏移(Bias)

通过小数点(百分比)控制控件在屏幕垂直/水平的百分比位置.

注意: 只有水平位置(上下/左右约束点都添加了约束)都添加约束, 该控件才支持百分比偏移

app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.69"

注意: 如果是约束的ConstraintLayout, 不需要这两个属性也可以设置百分比偏移

边距(Margin)

一般的边距没什么好讲的. 和以前一样.

android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

因为约束布局控件之前的关联性太强, 如果一个布局隐藏(gone)就可能导致整个布局的位置移动. 所以ConstraintLayout拥有隐藏边距属性

ConstraintLayout中使用Gone属性值

根据官方图可以看出Constraintlayout如果控件被隐藏并不会像其他布局一样坐标变成0,0点. 只是margin和宽高变成0.

layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom

以上边距属性会根据其约束的控件是否是隐藏(invisible不算)来生效, 同时margin失效.

宽高比(Radio)

通过设置宽或者高中的一个为match_constraint(0dp), 就可以设置控件的宽高比

matc_constraint的宽或高会根据另一边的尺寸变化来符合比例

宽高比分两种:

宽:高

app:layout_constraintDimensionRatio="2:1"

很简单就是宽比高, 默认受约束的就是**非**match_constraint(0dp)的一边.

受约束的是不会发生尺寸变化(如果是match_constraint和wrap_content时1:1比例会发生尺寸变化成正方形)

这一种我有点不太能理解, 官方感觉解释也比较模糊.

app:layout_constraintDimensionRatio="w,2:1"

我理解为颠倒了比例. w即设置比例为宽高, h为高比宽. 实际操作体验吧

辅助线(GuidLine)

辅助线用户是不可见的, 也没有宽高参数(你给他设置也无效). 只是在约束布局中做一个相对基准线而已.

<android.support.constraint.Guideline
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/guideline2"
      android:orientation="vertical"
      app:layout_constraintGuide_percent="0.41"
      />

辅助线有三种属性

  • begin 相对父布局左边边距
  • end 相对父布局右边边距
  • percent 相对父布局百分比
app:layout_constraintGuide_begin="20dp"

app:layout_constraintGuide_end="340dp"

app:layout_constraintGuide_percent="0.055555556"

辅助线有水平和垂直两种:

宽高(Width Hight)

宽高属性值

  • Fixed 固定值
  • Wrap_Content 包裹值
  • Match_Constraint “0dp”

Match_Constraint

理论上ConstraintLayout的宽高不再使用match_parent这一属性值. 取而代之的是0dp(称为match_constraint).

Important: MATCH_PARENT is not supported for widgets contained in a ConstraintLayout, though similar behavior can be defined by using MATCH_CONSTRAINT with the corresponding left/right or top/bottom constraints being set to "parent".

官方说明match_parent在ConstraintLayout中不被支持

match_constraint只有在水平或者垂直拥有两条方向的约束时才有效, 即匹配剩余全部空间. 如果只有水平只存在一条或者没有约束相当于wrap_content.

示例图:

如果你强行使用编辑器会自动帮你转换成固定dp值, 不过如果你仅仅是约束ConstraintLayout布局并没有问题.不能理解我说的什么自己动手试试.

链模式(Chain)

两个空间相互约束就会产生一个锁链. (注意布局编辑器中是无法通过拖动约束点相互约束, 我认为是bug)

只能通过多选居中的方式或者直接XML编辑.

app:layout_constraintHorizontal_chainStyle="packed"

链接在一起主要是可以设置不同的样式达到适配父容器宽度或者高度的效果. 注: 一个链还有第一个控件才需要设置(chainStyle)样式.

根据样式有三种参数值:

  • Spread 均布(默认样式)
  • Spread inside 头尾靠边, 其他中间均布
  • Packed 居中靠齐

官方有一张介绍图

虽然看着有五个,实际上属性还是那三个. 不过有加入权重和百分比偏移. Bias是偏移, weighted是权重.

权重(Weight)

和LinearLayout的wight属性一样. 不过只支持spread和spread_inside有效.

layout_constraintHorizontal_weight

同样可以编辑属性也可以鼠标修改

ConstraintSet

ConstraintLayout如果想对布局进行修改就必须使用到该类ConstraintSet. 对于常见的布局属性就不介绍了.

步骤:

  1. 克隆或者加载XMl布局
  2. 修改属性
  3. 应用到新的布局上

示例:

public class MainActivity extends AppCompatActivity {
    ConstraintSet mConstraintSet = new ConstraintSet(); // create a Constraint Set
    ConstraintLayout mConstraintLayout; // cache the ConstraintLayout


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.state1);
        Context context = this;

        mConstraintLayout = (ConstraintLayout) findViewById(R.id.activity_main);
        mConstraintSet.clone(mConstraintLayout); // 克隆一个布局到ConstraintSet
    }

    public void onClick(View view) {
        TransitionManager.beginDelayedTransition(mConstraintLayout); // 一行代码添加动画    
        mConstraintSet1.applyTo(mConstraintLayout); // 应用到新的布局
    }
}

删除所有约束

void clear (int viewId, 
                int anchor)

void clear (int viewId)

透明度

void setAlpha (int viewId, 
                float alpha)

旋转

旋转中心是控件的中心

void setRotationX (int viewId, 
                float rotationX)

void setRotationY (int viewId, 
                float rotationY)

缩放

同样是以控件为中心, 百分比浮点数

void setScaleX (int viewId, 
                float scaleX)

void setScaleY (int viewId, 
                float scaleY)

偏移

以控件中心偏移(不知道为何我写无效)

void setTransformPivot (int viewId, 
                float transformPivotX, 
                float transformPivotY)

void setTransformPivotX (int viewId, 
                float transformPivotX)

void setTransformPivotY (int viewId, 
                float transformPivotY)

设置边距

void setMargin (int viewId, 
                int anchor, 
                int value)

应用

void applyTo (ConstraintLayout constraintLayout)

克隆

复制一个ConstraintLayout布局到ConstraintSet中. 后面可以对ConstraintSet进行修改(即对复制的布局修改).

void clone (ConstraintSet set)

void clone (ConstraintLayout constraintLayout)

void clone (Context context, 
                int constraintLayoutId)

加载XML

不用Clone直接加载一个XML布局文件.

void load (Context context, 
                int resourceId)

创建约束

void connect (int startID, 
                int startSide, 
                int endID, 
                int endSide, 
                int margin)

问题

主要介绍一些可能是Bug或者是我知识层面不够的问题

tools命名

如果你使用了infer Constraint会发现自动生成了很多以tools开头的属性, 这些属性不用去管, 不对应用有任何影响.

tools:layout_constraintTop_creator="1"

控件无法拖动

主要是因为控件存在两个左右边距属性(start和left或者right和end)

删除start或者end即可. 个人认为是bug, 已经提交给Google.

布局编辑器中相互约束

要想使用Chain两个控件必须相互约束, 但是布局编辑器中无法相互约束

但是XML直接编辑或者以下方法还是可以相互约束的, 所以个人认为是bug

控件消失

如果出现控件不在编辑器内显示, 请检查编辑器属性坐标.

tools:layout_editor_absoluteX="137dp"
tools:layout_editor_absoluteY="-118dp"

猜你喜欢

转载自blog.csdn.net/liangjingkanji/article/details/77046764