news 2026/9/6 6:18:44

ConstraintLayout核心用法详解(五):Layer、ImageFilter*与MockView

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ConstraintLayout核心用法详解(五):Layer、ImageFilter*与MockView

整理旧电脑上的一些笔记

前言

  • ConstraintLayout核心用法详解(一):相对定位、边距、偏移与环形定位
  • ConstraintLayout核心用法详解(二):尺寸约束与链约束
  • ConstraintLayout核心用法详解(三):引导线、屏障、组和占位
  • ConstraintLayout核心用法详解(四):ConstraintSet、MotionLayout与Flow

今天继续整理ConstraintLayout

ConstraintLayout的特点:

  • 扁平布局,无嵌套,一个层级就可以绘制复杂布局;
  • 渲染性能高;
  • 集合了线性布局、相对布局、百分比布局的特点和大多数功能;
  • 支持可视化环境下拖拽绘制约束布局;
  • 轻松地为应用中使用的 UI 组件添加动画效果。

1. Layer

LayerConstraintLayout 2.0加入的新的辅助类,它同GuidelineGroup类似都是虚拟辅助。Layer是用来控制一组视图的移动和旋转,它和Group的场景不一样,Group是用来简单控制视图的可见性(VISIBILITYINVISIBILITY)。

我们可以把Layer的效果看成是一个ViewGroup,但是实际书写代码中并不需要把 view 包裹进去Layer

下面看具体 XML 代码示例:

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns: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/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".constraintlayout.LayerActivity"><ImageViewandroid:id="@+id/iv_android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="50dp"android:src="@mipmap/ic_launcher"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/><TextViewandroid:id="@+id/tv_android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="android"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@id/iv_android"/><androidx.constraintlayout.helper.widget.Layerandroid:id="@+id/layer"android:layout_width="wrap_content"android:layout_height="wrap_content"app:constraint_referenced_ids="iv_android,tv_android"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"/><Buttonandroid:id="@+id/btn_rotation"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="rotation"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>

上面 XML 代码中关键属性:

  • constraint_referenced_ids:指定要控制的视图ID,如iv_android、tv_android,逗号分隔

Kotlin 代码示例:

classLayerActivity:AppCompatActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_layer)vallayer=findViewById<Layer>(R.id.layer)valbutton=findViewById<Button>(R.id.btn_rotation)button.setOnClickListener{valanimator=ValueAnimator.ofFloat(0f,360f)animator.duration=2000animator.addUpdateListener{animator->layer.rotation=animator.animatedValueasFloat layer.scaleX=2.0flayer.scaleY=2.0flayer.translationX=100flayer.alpha=0.3f}animator.start()}}}

上面代码因为比较简单,直接使用Kotlin原始方法findViewById,实际推荐使用viewBinding,减少模板代码。

运行效果图:

2.ImageFilterView 和 ImageFilterButton

ImageFilterViewImageFilterButton也都是ConstraintLayout 2.0新添加的控件。它是 Android 第一次提供原生支持图像圆角、滤镜(饱和度、亮度、对比度和色温)、交叉淡入(crossfade)等特性。

以往产品中遇到需要圆角图形,如头像、歌曲专辑封面等,往往采用自定义View或第三方控件实现,有了ImageFitlerView就很好的解决了该场景问题。

2.1 ImageFilterView

首先介绍ImageFilterView支持的属性:

  • altSrc:设置一个和src属性不同的图,用来实现交叉淡入淡出效果
  • saturation:设置饱和度。其中0=灰度,1=原始图,2=超饱和
  • brightness:设置亮度。0=全黑,1=原始图,2=亮度加倍
  • warmth:设置色温。1=中性,2=暖色,0.5=冷色
  • contrast:设置图像对比度。1=不变,0=灰色,2=高对比度
  • crossfade:设置两张图像间的混合程度。0=完全显示src图,1=完全显示altSrc图像
  • round:设置圆角半径
  • roundPercent:设置圆角半径为短边长的一个比例值
  • overlay:设置替代图(altSrc)是以叠加方式淡入原始图像上还是与原始图像进行交叉淡入淡出。默认=true

XML代码展示:

<androidx.constraintlayout.utils.widget.ImageFilterViewandroid:id="@+id/iv_avatar"android:layout_width="100dp"android:layout_height="100dp"android:src="@drawable/img_avatar"app:altSrc="@drawable/img_duck"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:round="20dp"/>

Kotlin代码展示:

binding.sliderSaturation.addOnChangeListener{slider,value,fromUser->if(fromUser){valintValue=value.toInt()Toast.makeText(this,"$intValue",Toast.LENGTH_SHORT).show()when(intValue){0->binding.ivAvatar.saturation=0f1->binding.ivAvatar.saturation=1f2->binding.ivAvatar.saturation=2f}}}binding.sliderBrightness.addOnChangeListener{slide,value,fromUser->if(fromUser){valintValue=value.toInt()when(intValue){0->binding.ivAvatar.brightness=0f1->binding.ivAvatar.brightness=1f2->binding.ivAvatar.brightness=2f}}}binding.sliderWarmth.addOnChangeListener{slide,value,fromUser->if(fromUser){valfloatValue=value.toFloat()when(floatValue){0.5f->binding.ivAvatar.warmth=0.5f1.0f->binding.ivAvatar.warmth=1f2.0f->binding.ivAvatar.warmth=2f}}}binding.sliderContrast.addOnChangeListener{slide,value,fromUser->if(fromUser){valintValue=value.toInt()when(intValue){0->binding.ivAvatar.contrast=0f1->binding.ivAvatar.contrast=1f2->binding.ivAvatar.contrast=2f}}}binding.seekbarCrossfade.setOnSeekBarChangeListener(object:SeekBar.OnSeekBarChangeListener{overridefunonProgressChanged(seekbar:SeekBar?,progress:Int,fromUser:Boolean){if(fromUser){valpercentage=progress/100.0fbinding.ivAvatar.crossfade=percentage}}overridefunonStartTrackingTouch(seekbar:SeekBar?){}overridefunonStopTrackingTouch(seekbar:SeekBar?){}})

整体的代码示例还是很简单的,我们结合下面的效果图来加深理解即可。

2.2 ImageFilterButton

ImageFilterButtonAppCompatImageButton的子类,可以用来显示、组合和过滤图像。它与上面提到的ImageFilterView拥有相同的属性,所不一样的就是ImageFilterButton兼具 Button 的特性。

直接XML代码展示:

<androidx.constraintlayout.utils.widget.ImageFilterButtonandroid:id="@+id/btn_share"android:layout_width="80dp"android:layout_height="80dp"android:layout_marginTop="20dp"android:background="#E91E63"android:src="@drawable/icon_share"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@id/seekbar_crossfade"app:round="40dp"/><androidx.constraintlayout.utils.widget.ImageFilterButtonandroid:id="@+id/btn_favorite"android:layout_width="80dp"android:layout_height="80dp"android:layout_marginTop="20dp"android:background="#E91E63"android:src="@drawable/icon_favorite"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@id/btn_share"app:round="40dp"/>

效果图:

ImageFilterButton还是比较好理解的,它支持的饱和度、对比度等特性参考上面ImageFilterView示例,这里也就不再赘述了。

3. MockView

讲解MockView前先来看一张图。

一些产品稿中会使用上图中带对角线的矩形来占位,方便模拟一些视图,而MockView也正是这样的用途。

A view that is useful for prototyping layouts.

MockView在布局中作为占位视图,模拟真实数据或复杂视图的布局效果。实际开发中,存在下面的场景:

  1. 真实数据还没有,比如用户头像;
  2. 某些View是动态加载的,比如RecyclerView加载的item;
  3. 某些View是有不同的状态的,比如loading、空数据提示

我们当然可以在 Java(Kotlin) 中用代码模拟假数据来实现UI效果,但当我们使用ConstraintLayout作为根布局时候,更推荐MockView来模拟这些数据存在。

下面是MockView的一些属性:

  • mock_label:显示字体
  • mock_labelColor:字体颜色
  • mock_labelBackgroundColor:字体背景色
  • mock_diagonalsColor:对角线颜色
  • mock_showDiagonals:是否显示对角线

XML代码示例:

<androidx.constraintlayout.utils.widget.MockViewandroid:id="@+id/background"android:layout_width="0dp"android:layout_height="100dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:mock_label="LOGO或风景图"app:mock_labelBackgroundColor="#9C27B0"app:mock_labelColor="@color/white"app:mock_showDiagonals="true"/><androidx.constraintlayout.utils.widget.MockViewandroid:id="@+id/login"android:layout_width="200dp"android:layout_height="40dp"android:layout_marginTop="30dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@id/background"app:mock_diagonalsColor="#2196F3"app:mock_label="登录"app:mock_showDiagonals="true"/><androidx.constraintlayout.utils.widget.MockViewandroid:id="@+id/register"android:layout_width="200dp"android:layout_height="40dp"android:layout_marginTop="30dp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@id/login"app:mock_diagonalsColor="#2196F3"app:mock_label="注册"app:mock_showDiagonals="true"/>

预览图:

MockView作为辅助设计的控件,它不能设置事件而且正式发布项目前建议要移除MockView,保持布局干净。

4.参考资料

  • Developer-ConstraintLayout:https://developer.android.google.cn/reference/androidx/constraintlayout/widget/ConstraintLayout
  • ConstraintLayout历史版本:https://developer.android.google.cn/jetpack/androidx/releases/constraintlayout?hl=zh_cn
  • ImageFilterView:https://developer.android.google.cn/reference/kotlin/androidx/constraintlayout/utils/widget/ImageFilterView?hl=en
  • ImageFilterButton:https://developer.android.google.cn/reference/androidx/constraintlayout/utils/widget/ImageFilterButton?hl=en
  • MockView:https://developer.android.google.cn/reference/kotlin/androidx/constraintlayout/utils/widget/MockView?hl=en
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 6:18:28

Copilot 能换成本地吗?本地化 AI 编程助手可行性分析

1. 引言&#xff1a;为什么想换成本地 Copilot随着 AI 编程助手普及&#xff0c;越来越多开发者开始思考&#xff1a;Copilot 能换成本地吗&#xff1f;本文从数据隐私、网络依赖、成本控制等角度&#xff0c;分析本地化替代方案的可行性与落地路径。2. 本地化替代方案概览目前…

作者头像 李华
网站建设 2026/9/6 6:18:18

Linux从开始到入门,看这篇就够了!

一、介绍操作系统是管理硬件资源(CPU,内存,磁盘&#xff0c;网络)并为应用软件提供运行环境的系统软件.内核是操作系统的核心,承担进程调度,内存管理。文件系统与设备驱动二、Linux命令Shell是命令解释器 讲用户输入翻译为系统调用交由内核执行 $表示普通用户 #表示权限更高的管…

作者头像 李华
网站建设 2026/9/6 6:17:56

嵌入式C语言面试题:底层原理与工程实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 6:16:50

LiteMES 第 7 天:取消工单时,产品和物料到底怎么处理

LiteMES 第 7 天&#xff1a;取消工单时&#xff0c;产品和物料到底怎么处理本文记录 LiteMES 第 7 天的工单状态机设计过程。当前完成的是业务与五项对齐设计&#xff0c;尚未进入源码实现。一、工单取消不是删除 制造现场会出现客户取消、工程变更、长期缺料、设备故障或质量…

作者头像 李华
网站建设 2026/9/6 6:13:22

Muse Spark 1.3 接入实战:两条路径的验证与选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/6 6:12:21

【STM32 物联网实训】RFID 三连:读卡、写卡、刷卡

这一篇记录物联网方向的 RFID 系列&#xff1a;读取、写入、刷卡消费充值&#xff0c;同样是学校的智联场景实训箱&#xff08;STM32L431 Keil MDK5 HAL 库&#xff09;。RFID 是物联网感知层里 "身份识别" 的代表技术&#xff0c;门禁、校园卡、食堂刷卡、公交卡全…

作者头像 李华