最强大的布局——约束布局(ConstraintLayout)的一些技巧

2023-11-02

一.使用viewBinding
1.想开启那个模块的viewBinding就进入对应模块的build.gradle
在这里插入图片描述
2.进入app的build.gradle
在这里插入图片描述
开启viewbinding

viewBinding {
        enabled = true
    }

3.当你开启viewbinding后,app目录下的所有布局文件都会生成一个绑定类。这个类的类名是以xml布局文件名去掉下换线后,单词首字母大写加上Binding命名的。如activity_main.xml生成的绑定类为ActivityMainBinding.

如果你不想生成绑定类,也很简单,将tools:viewBindingIgnore=“true” 属性添加到相应布局文件的根视图中。
在这里插入图片描述
使用就更简单了,如下

package com.example.animationtest

import android.os.Bundle
import android.os.PersistableBundle
import androidx.appcompat.app.AppCompatActivity
import com.example.animationtest.databinding.ConstrainBinding

class Constraint:AppCompatActivity() {
    private val viewBinding=ConstrainBinding.inflate(layoutInflater)
    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)
        setContentView(viewBinding.root)
    }
}

viewBinding.root就是布局的根布局

二.开发中可能会遇到的场景

1.当A或者C宽度固定或者为wrap_content,你想要B的宽度自适应。

其实这个场景可以分解为:

B.width=屏幕宽度-A.width-C.width(视情况可能还会减去margin或padding)

在这里插入图片描述
如果用约束布局就要用android:layout_width="0dp"来解决这个问题,那就是把B的宽度设置为0dp。

如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/text_a"
        android:layout_width="40dp"
        android:layout_height="wrap_content"
        android:text="A"
        android:background="@color/black"
        android:textColor="@color/white"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/text_b"
        tools:ignore="MissingConstraints" />

    <TextView
        android:id="@+id/text_b"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="B"
        android:textColor="@color/white"
        android:background="@color/design_default_color_primary_dark"
        app:layout_constraintStart_toEndOf="@id/text_a"
        app:layout_constraintEnd_toStartOf="@id/text_c"
        tools:ignore="MissingConstraints" />

    <TextView
        android:id="@+id/text_c"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:text="C"
        android:textColor="@color/teal_200"
        app:layout_constraintStart_toEndOf="@id/text_b"
        app:layout_constraintEnd_toEndOf="parent"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>

布局很简单,就三个Textview,把三个控件相互约束,再把把B的宽度设置为0dp。

2.如果想要三个控件平分宽度
2.1 如果你没有背景,就把三个控件相互约束,但三个控件的宽度都必须是wrap_content或固定宽度(这个应该都能理解吧,为match_parent其中一个子布局就充满了父控件了,就别谈自适应了)。

在这里插入图片描述
2.2 你有背景就把三个控件的宽度都设置为0dp

其实这个场景可以分解为:

任意一个的宽度=(屏幕宽度-(视情况可能减去margin或padding))/3
在这里插入图片描述

<?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:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text_a"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/black"
        android:text="A"
        android:textColor="@color/white"
        app:layout_constraintEnd_toStartOf="@id/text_b"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="MissingConstraints" />

    <TextView
        android:id="@+id/text_b"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/design_default_color_primary_dark"
        android:text="B"
        android:textColor="@color/white"
        app:layout_constraintEnd_toStartOf="@id/text_c"
        app:layout_constraintStart_toEndOf="@id/text_a"
        tools:ignore="MissingConstraints" />

    <TextView
        android:id="@+id/text_c"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="C"
        android:textColor="@color/teal_200"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/text_b"
        tools:ignore="MissingConstraints" />

</androidx.constraintlayout.widget.ConstraintLayout>

现在基本上都是用约束布局,这就像属性动画一样,它可以适用所有场景。

三.动态改变布局

1.获取屏幕宽度
可以去下面的博客去看,写的很好
Android 获取屏幕宽度和高度的几种方法
当你获取了屏幕宽度或高度,你就可以写一写适配Android的布局了。

val outSize = DisplayMetrics()
        windowManager.defaultDisplay.getRealMetrics(outSize)
        val width = outSize.widthPixels
        val height = outSize.widthPixels

        viewBinding.textA.updateLayoutParams<ConstraintLayout.LayoutParams> {
            topMargin=width
        }

2.动态改变布局

2.1 改变布局属性
1.viewBinding.textA.updateLayoutParams<ConstraintLayout.LayoutParams> { topMargin=width }
ConstraintLayout.LayoutParams 这里是父布局的LayoutParams,
比如我的text A的父布局就是ConstraintLayout

2.2 改变布局约束

 val constrainSet = ConstraintSet().apply { clone(viewBinding.root) }
        constrainSet.connect(
            viewBinding.textC.id,ConstraintSet.START,viewBinding.textA.id,ConstraintSet.END
        )
        constrainSet.applyTo(viewBinding.root)

val constrainSet = ConstraintSet().apply { clone(viewBinding.root) }
这段话就是复制一份父布局的约束,方法有三个如下:

set.clone(constraintLayout: ConstraintLayout);
set.clone(set: ConstraintSet);
set.clone(context: Context, constraintLayoutId: Int);

这里需要注意,在调用clone()方法的时候,必须保证这个父布局的所有子布局都设置了 id,不然会报错,这跟它的内部实现原理有关,有兴趣可以去看一下源码。

  1. 设置组件之间的约束,常用方法有:
set.connect(startID: Int, startSide: Int, endID: Int, endSide: Int, margin: Int)
 
set.connect(startID: Int, startSide: Int, endID: Int, endSide: Int)
constrainSet.connect(
            viewBinding.textC.id,ConstraintSet.START,viewBinding.textA.id,ConstraintSet.END,20
        )

这句话的意思就是: 修改一个id为textC的约束,依赖的约束组件为一个id为textA的控件,修改为textC的左边和textA的右边对其,边距margin为20px:

3.然后把新的布局约束设置到原来的布局

constrainSet.applyTo(viewBinding.root)

4.View.post()
这是为了解决布局还没执行View的meaure()而获取宽高为0的其中一个解决方案。

viewBinding.textB.post 
{ 
val width=viewBinding.textB.width
val width=viewBinding.textB.measuredWidth
val height=viewBinding.textB.height
        }

大家应该注意到我上面用了width和measuredWidth
这两者有何区别呢
很简单就是字母的区别(开个冷玩笑)
measuredWidth:它的值在measure方法运行后会确定
width:它的值在layout方法运行后会确定

这里引用下这个博主的一段话
Android是消息驱动的模式,View.post的Runnable任务会被加入任务队列,并且等待第一次TraversalRunnable执行结束后才执行,此时已经执行过一次measure,layout过程了,所以在后面执行post的Runnable时,已经有measure的结果,因此此时可以获取到View的宽高。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

最强大的布局——约束布局(ConstraintLayout)的一些技巧 的相关文章

随机推荐

  • 专访用自己姓氏命名编译器YC++的创始人

    在CSDN的论坛里看到了这样的一条帖子 请使用中国人开发的C C 编译器 网页浏览器内核 并提供了该软件的下载地址 从大家的跟帖来看很多人 是很有兴趣的 但是作者并没有留下太多的介绍说明类的文字 为了一探究竟 我拨通了作者留下的电话并完成了
  • Ubuntu 16.04设置root用户登录图形界面

    Ubuntu默认的是root用户不能登录图形界面的 只能以其他用户登录图形界面 这样就很麻烦 因为权限的问题 不能随意复制删除文件 用gedit编辑文件时经常不能保存 只能用vim去编辑 下面以Ubuntu 16 04版为例说明 1 打开终
  • STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法

    STM32实战项目经验 HAL RCC OscConfig中程序卡死问题解决办法 工程环境 STM32CUBEIDE STM32F405VG 现象复现 项目中一个是IAP程序 另一个是APP程序 两个程序都是使用STM32CubeIDE生成
  • 搜索题目综合

    BFS 1 小X学游泳 题解 枚举每一个点作为连通块的起点 求得连通块大小 然后打擂台求最值即可 参考代码 include
  • element-ui和element-plus的自定义列表格用法

    前言 element plus 这个 UI 组件库 虽说基本和 vue2 element ui 差不多 但还是有点区别 以至于按emenent ui的写法来写会发现报错 下面我将讲解一下element ui和element plus的自定义
  • 一文彻底讲清Linux tty子系统架构及编程实例

    摘要 本文详细解读了linux系统下的tty子系统的深层次原理和架构 并参考了LDD3中的代码实例讲述了无硬件下实现一个简单的tty设备驱动模块的编写 对了解tty子系统及下部串口驱动模块的学习有较好的参考价值 1 tty设备简介 tty一
  • 抖音广告IOS/Android接入笔记:

    一 抖音广告接入 Android接入 注意 内容输出对接中已包含广告对接 建议使用广告4 6 0 7版本 如使用其他广告版本建议做好自测 2600及以上版本 需要使用如下Maven命令 火山引擎maven仓库地址 maven url htt
  • 红帽系统服务器格式化,Redhat Linux默认的文件系统是什么格式?

    满意答案 现在Redhat Linux默认的文件系统格式是ext4 可以通过如下多种方法查询文件系统类型 1 mount mount dev sda1 on type ext4 rw errors remount ro user xattr
  • 第五周总结

    已知字符串 this is a test of java 按要求执行以下操作 统计该字符串中字母s出现的次数 统计该字符串中子串 is 出现的次数 统计该字符串中单词 is 出现的次数 实现该字符串的倒序输出 public class da
  • MySQL之常见的CRUD面试题【下】

    Welcome Huihui s Code World 接下来看看由辉辉所写的关于MySQL数据库的相关操作吧 目录 Welcome Huihui s Code World 导读 一 MySQL常见的内置函数 1 字符串函数 2 数值函数
  • 测绘地理信息标准规范汇总下载

    经常 我们要下载一些相关的规范来指导作业 每次都在网上找 这里一次性全部整理好 欢迎大家来下载 打包下载 链接 百度网盘地址 分页下载 一 国家测绘局制定的测绘地理信息国家标准 专题地图信息分类与代码 GBT 18317 2001 被GBT
  • 4-C语言-冒泡排序以及数组名的使用

    问题 给数组进行从小到大的升序排序 思想 一般给冒泡排序 进行封装 写成一个函数 这就需要让数组传进去 而传数组 实际传的数组的首元素的地址 因此如果在冒泡内部 进行数组数据个数的计算 用sizeof a sizeof a 0 实际上为1
  • Braft--工作日记

    建议在阅读本笔记之前先观看此网址的动画Raft 分布式共识算法动画演示 首先bRaft是实现分布式共识的协议 一个节点可以处于三种状态 Follower跟随者状态 Candidate候选者状态 Leader领导者状态 而所有的节点都以跟随者
  • 计算机毕业设计SSM大型零售电商平台——购物车管理子系统【附源码数据库】

    项目运行 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEclispe Sts都支持 项目技术 SSM mybatis Ma
  • softmax函数的定义及求导

    本文中 x0 x1 xm x 0 x 1 x m 代表一个向量 也就是一个 m m行1列的矩阵 在监督式的深度学习中 输入通常是一个向量 用xx表示 输出 y y则可以分为多种情况 标量 yy表示输入 x x属于某一类别的概率 向量 此时输
  • AutoDev 1.1.3 登场,个性化 AI 辅助:私有化大模型、自主设计 prompt、定义独特规则...

    在过去的半个月里 我们为开源辅助编程工具 AutoDev 添加了更强大的自定义能力 现在你可以 使用自己部署的开源大模型 自己配置 Intellij IDEA 中的行为 自定义开发过程中的规范 当然了 如果您自身拥有开发能力的话 建议您自己
  • 绕过身份检测,破解Android SU

    http www 61ic com Mobile Android 201207 43661 html 由于Android底层是Linux内核 故了解了Linux的权限管理后就可以知道ROOT的原理 具体可以访问 Android系统权限和ro
  • js基础-语句

    语句 表达式在JavaScript中是短语 而语句 statement 就是JavaScript整句或命令 JavaScript语句是以分号结束 默认情况下 JavaScript解释器依照语句的编写顺序依次执行 1 表达式语句 1 复合语句
  • linux服务器部署docker版nginx(nginx容器化)

    为了服务器安全 nginx端口不直接暴漏在外 现在服务器使用了docker版nginx 记录下使用步骤 docker安装就不再叙述 之前有写 分为2种适用于服务器能上网和不能上网的情况 这里写的一个sh文件和dockerfile文件 用于d
  • 最强大的布局——约束布局(ConstraintLayout)的一些技巧

    一 使用viewBinding 1 想开启那个模块的viewBinding就进入对应模块的build gradle 2 进入app的build gradle 开启viewbinding viewBinding enabled true 3