android约束布局ConstraintLayout

android约束布ConstraintLayout

说明

  • 约束布局中关于控件的大小(也叫视图尺寸)主要有三种:
    • wrap_content:自适应控件内容大小
    • fixed:固定大小
    • match constraints: 填满布局,在xml中就是表现为0dp

常用操作

居中

  • 如果想让控件居中,设置bias百分之50即可,如下图
    在这里插入图片描述
  • bias表示控件在水平或垂直方向上的位置比例,必须在水平方向左右或垂直方向上下都有约束并且视图尺寸为fixed或者wrap_content时才会生效
  • 在这里插入图片描述
  • 利用bias我们就可以把控件放置相应比例的地方,注意bias范围是0.0~1.0

控件按比例显示

  • 如果想让控件按比例展示,首先先切换为Match Constraints(即 android:layout_width=“0dp”),如下图
    在这里插入图片描述
  • 然后就可以看到左上角出现三角形
    在这里插入图片描述
  • 点击三角形即可出现设置比例的ratio
    在这里插入图片描述
  • 在xml中则体现为app:layout_constraintDimensionRatio=“w,1:1”,意思就是宽度与原本高度的比例为1:1
  • 这里的原本高度就是指如果不加上这一行app:layout_constraintDimensionRatio="w,1:1"控件所呈现出来的高度
  • 如下图,控件原本高度是三行文字的高度(这里假设高度是20dp)
    在这里插入图片描述
  • 现在加上这一行app:layout_constraintDimensionRatio="w,2:1"之后宽度就是原本高度的两倍了(为40dp,这里不要误以为"w,2:1"是最终宽度与最终高度比为2:1,而应该是最终宽度与原本高度比为2:1)
    在这里插入图片描述
  • 再举个例子吧,我们有时候希望控件宽度是屏幕宽度,而宽高按16:9的比例动态计算,那么我们就可以如下设置

在这里插入图片描述

  • layout_constraintDimensionRatio非常适合那种一边长度已经确定了,而另一边想要按比例计算的控件尺寸
  • 如果想让最终宽高比完全按照设定的比例,那么就需要控件的宽高都为match constraints,即
 <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="16:9"  <!-- 当layout_width和layout_height都为match_constraints时,16:9和h,16:9是一样的-->
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
  • 当只有layout_width为match constraints时,layout_constraintDimensionRatio的"16:9"和"w,16:9"是一样的,同理,当只有layout_height为match constraints时,layout_constraintDimensionRatio的"16:9"和"h,16:9"是一样的
  • 当layout_width和layout_height都为match constraints时,“16:9”和"h,16:9"是一样的,都是宽度占满后,宽度与高度比例为16:9,即高度随着宽度变化而变化
  • 一般来说,比例前写了“w”,表明宽度是随着高度按比例变化的;同理,“h”则表明高度是随着宽度按比例变化的
  • 当宽或高为match_parent或fixed,也就是一边基本已知的情况下,match constraints的这一边的计算规则如下:
 boolean verticalDimensionKnown = verticalBehavior == DimensionBehaviour.MATCH_PARENT || verticalBehavior == DimensionBehaviour.FIXED;
 boolean horizontalDimensionKnown = horizontalBehavior == DimensionBehaviour.MATCH_PARENT || horizontalBehavior == DimensionBehaviour.FIXED;
 boolean horizontalUseRatio = horizontalMatchConstraints && widget.mDimensionRatio > 0.0F;
 boolean verticalUseRatio = verticalMatchConstraints && widget.mDimensionRatio > 0.0F;
 if (horizontalUseRatio && verticalDimensionKnown) {
	   ratio = widget.mDimensionRatio;
	    width = (int)(0.5F + (float)height * ratio);
	} else if (verticalUseRatio && horizontalDimensionKnown) {
	    ratio = widget.mDimensionRatio;
	    height = (int)(0.5F + (float)width / ratio);
	}

视图尺寸为match constraints

  • 当视图尺寸为match constraints时,你可以设置控件其他属性
    • layout_constraintWidth_default:spread是默认行为,wrap则可以使得控件内容区长度不会超出屏幕
    • layout_constraintWidth_min:控件最小宽度
    • layout_constraintWidth_max:控件最大宽度
  • 当你使用margin和wrap_content时,你会发现控件内容区过长时会超出屏幕,如下
  • 在这里插入图片描述
    在这里插入图片描述
  • 上面红框的地方明显不是我们想要的,为了解决这个问题,我们可以改为
    在这里插入图片描述
    在这里插入图片描述
  • 这样设置后就不会超出屏幕了
  • 注意,layout_constraintWidth_default=“wrap” 后期已过时,不再推荐使用

    layout_constraintWidth_default=“wrap” is deprecated.
    Use layout_width=“WRAP_CONTENT” and layout_constrainedWidth=“true” instead.

  • 显然上面的问题只是解决了TextView在宽度为铺满的情况下的超出屏幕的问题,但是如果我们想TextView是wrap_content的,内容过长时又不超出屏幕呢
  • 这就需要再配合上bias了
  • 在这里插入图片描述
  • 我们先看内容短的情况

在这里插入图片描述

  • 再看内容长的情况
    在这里插入图片描述

删除约束

  • 在windows上通过按住Ctrl再点击约束即会变成红色,此时就可以删除约束了
    在这里插入图片描述

屏障约束

  • 首先右键添加一个barrier
    在这里插入图片描述
  • 添加完后在component tree窗口可以看到该组件
    在这里插入图片描述
  • 然后就可以把放在屏障里的控件拖拽到barrier里面,如图
    在这里插入图片描述
  • 最后设置下方向,然后拖动下放进barrier里的控件试试看
    在这里插入图片描述

  • 如果想实现如下效果,那么就要使用链
    在这里插入图片描述

  • 框选要组成链的控件后,右键选择chains即可增加水平链或垂直链 在这里插入图片描述

  • 之后可以选择对齐方式
    在这里插入图片描述

  • 在这里可以选择不同的style
    在这里插入图片描述

  • Spread:视图是均匀分布的(在考虑外边距之后)。这是默认值。

  • Spread inside:第一个和最后一个视图固定在链两端的约束边界上,其余视图均匀分布。

  • Weighted:当链设置为 spread 或 spread inside 时,您可以通过将一个或多个视图设置为“match constraints”(0dp) 来填充剩余空间。默认情况下,设置为“match constraints”的每个视图之间的空间均匀分布,但您可以使用 layout_constraintHorizontal_weight 和 layout_constraintVertical_weight 属性为每个视图分配重要性权重。如果您熟悉线性布局中的 layout_weight 的话,就会知道该样式与它的原理是相同的。因此,权重值最高的视图获得的空间最大;相同权重的视图获得同样大小的空间。

  • Packed:视图打包在一起(在考虑外边距之后)。 然后,您可以通过更改链的头视图偏差调整整条链的偏差(左/右或上/下)

动画效果

  • 在约束布局中可以使用 ConstraintSetTransitionManager 为尺寸和位置元素的变化添加动画效果,注意这种效果只针对位置和尺寸,不包含颜色等其他
  • 而且这种效果的实现需要写两个布局文件,分别作为开始和结束关键帧
ActivityConstraintBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityConstraintBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
    }

    public void onClickAnim(View view) {
        if (view.isSelected()) {
            view.setSelected(false);
            anim(R.layout.activity_constraint);
        } else {
            view.setSelected(true);
            anim(R.layout.activity_constraint_keyframe_two);

        }
    }

    /**
     * 这种效果只针对位置和尺寸,不包含颜色等其他
     * @param layoutId
     */
    private void anim(@LayoutRes int layoutId) {
        ConstraintSet constraintSet = new ConstraintSet();
        constraintSet.load(this, R.layout.activity_constraint_keyframe_two);
        TransitionManager.beginDelayedTransition(binding.getRoot());
        constraintSet.applyTo(binding.getRoot());
    }

layout_goneMarginXXX

  • 你是否遇到过在约束布局中layout_marginBottom设置无效的情况
  • 比如
    在这里插入图片描述
  • 此时你会发现text1与text2之间并没有间隔10dp,有的人可能会说直接在text2中设置layout_marginTop即可,在text1与text2皆可见的时候确实可以这么做,但是如果在隐藏text1时,我们想让text2的layout_marginTop自动失效呢,这可咋办
  • 我们可以借助layout_goneMarginXXX,如下
  • 在这里插入图片描述
  • 这样在text1和text2都设置为可见时,它们直接会间隔10dp;在text1隐藏时,layout_goneMarginTop会生效而layout_marginTop则会失效,从而达到我们想要的效果

角标位置

  • 我们经常需要某个view(称为anchor)的不同位置放置一些角标,如下图
    在这里插入图片描述
<!-- 在anchor视图右上角-->
 <View
       ...
        app:layout_constraintBottom_toTopOf="@+id/anchor"
        app:layout_constraintEnd_toEndOf="@+id/anchor"
        app:layout_constraintStart_toEndOf="@+id/anchor"
        app:layout_constraintTop_toTopOf="@+id/anchor" />

<!-- 在anchor视图右下角-->
 <View
       ...
       app:layout_constraintStart_toEndOf="@id/anchor"
        app:layout_constraintEnd_toEndOf="@id/anchor"
        app:layout_constraintTop_toBottomOf="@id/anchor"
        app:layout_constraintBottom_toBottomOf="@id/anchor" />

<!-- 在anchor视图左上角-->
 <View
       ...
        app:layout_constraintStart_toStartOf="@id/anchor"
        app:layout_constraintEnd_toStartOf="@id/anchor"
        app:layout_constraintTop_toTopOf="@id/anchor"
        app:layout_constraintBottom_toTopOf="@id/anchor" />

<!-- 在anchor视图左下角-->
 <View
       ...
       app:layout_constraintStart_toStartOf="@id/anchor"
        app:layout_constraintEnd_toStartOf="@id/anchor"
        app:layout_constraintTop_toBottomOf="@id/anchor"
        app:layout_constraintBottom_toBottomOf="@id/anchor" />

右侧跟随左侧,但宽度不够时右侧显示完整,左侧被挤压

  • 如下效果
    在这里插入图片描述

在这里插入图片描述

  • 首先可以将左侧和右侧绑成链,style设置为packed,然后为左侧设置app:layout_constrainedWidth="true"和app:layout_constraintHorizontal_bias="0"即可
  • 示例代码如下
<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/right"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />

        <TextView
            android:id="@+id/right"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:background="@drawable/bg_label"
            android:paddingLeft="6dp"
            android:paddingRight="6dp"
            android:text="群聊"
            app:layout_constraintBottom_toBottomOf="@id/left"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/left"
            app:layout_constraintTop_toTopOf="@id/left" />

    </androidx.constraintlayout.widget.ConstraintLayout>

参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值