进阶实战:基于android_maskable_layout 源码扩展自定义遮罩ViewGroup的完整指南

📅 发布时间:2026/8/16 15:33:54
进阶实战:基于android_maskable_layout 源码扩展自定义遮罩ViewGroup的完整指南
进阶实战基于android_maskable_layout 源码扩展自定义遮罩ViewGroup的完整指南【免费下载链接】android_maskable_layoutA library that easily allows you to mask layouts/viewgroups项目地址: https://gitcode.com/gh_mirrors/an/android_maskable_layoutandroid_maskable_layout 是一款轻量级的 Android 遮罩布局开源库它允许开发者通过简单的 XML 属性或一行代码为任意 View 和 ViewGroup 添加圆形、星形甚至动画遮罩效果。本文将从源码角度剖析其核心实现并给出 3 个可落地的扩展方案帮助你从「会用」进阶到「会改」打造属于自己的自定义遮罩 ViewGroup。无论你是刚接触 Android 自定义 View 的新手还是想提升 UI 表现力的普通开发者这份实战指南都能让你快速上手。android_maskable_layout 是什么一个给 ViewGroup 加遮罩的轻量级库简单来说android_maskable_layout只做了一件事把任意 ViewGroup 变成一块「画布」再用一张遮罩图Drawable去裁剪它的子 View 显示区域。它的核心类MaskableFrameLayout继承自系统FrameLayout因此任何原本能放进 FrameLayout 的布局和控件都能直接获得遮罩能力。它的典型使用方式是在 XML 中声明几乎零代码侵入com.christophesmet.android.views.maskableframelayout.MaskableFrameLayout android:layout_width100dp android:layout_height100dp app:maskdrawable/masking_masking_20 app:porterduffxfermodeDST_IN ImageView android:layout_widthmatch_parent android:layout_heightmatch_parent android:scaleTypecenterCrop android:srcdrawable/unicorn/ /com.christophesmet.android.views.maskableframelayout.MaskableFrameLayout对比上面的演示动图就能直观看到同样一张独角兽图片无遮罩时是矩形加上圆形遮罩就变圆加上星形遮罩就变星形甚至还能加载 60 帧的逐帧动画遮罩。核心原理速览MaskableFrameLayout 源码到底做了什么扩展自定义遮罩 ViewGroup 之前先花 3 分钟看懂源码。整个库的核心只有两个文件核心类library/src/main/java/com/christophesmet/android/views/maskableframelayout/MaskableFrameLayout.java自定义属性library/src/main/res/values/attrs_maskable_framelayout.xml第一步把遮罩 Drawable 转成 Bitmap遮罩本质上是一张与 View 同尺寸的位图。在makeBitmapMask()方法中库会把传入的 Drawable 绘制到一个ARGB_8888的 Bitmap 上。关键前提是 View 必须先完成测量宽高大于 0所以库通过ViewTreeObserver注册了全局布局监听等尺寸确定后再生成遮罩。第二步用 PorterDuff 混合模式完成裁剪遮罩的显示发生在重写dispatchDraw(Canvas)中MaskableFrameLayout.java第 207-216 行先绘制所有子 View再把遮罩 Bitmap 以指定的PorterDuffXfermode混合上去。默认使用DST_IN即「保留子 View 中与遮罩重叠的部分」从而实现形状裁剪。第三步通过三个自定义属性控制行为属性文件定义了mask遮罩 Drawable、porterduffxfermode17 种混合模式枚举和anti_aliasing抗锯齿开关全部通过TypedArray在构造时读取。扩展前的准备工作下载源码与工程结构首先获取源码git clone https://gitcode.com/gh_mirrors/an/android_maskable_layout工程采用多模块结构settings.gradle中声明了library和Sample两个模块结构清晰android_maskable_layout/ ├── library/ # 核心库模块AAR │ └── src/main/java/com/christophesmet/android/views/maskableframelayout/ │ └── MaskableFrameLayout.java # 全部核心逻辑 └── Sample/ # 演示工程 ├── MainActivity.java # 动画遮罩触发逻辑 └── res/drawable/animation_mask.xml # 60帧逐帧动画遮罩建议先运行 Sample 模块查看效果再进入源码研读效率更高。三个实战扩展方向打造你的自定义遮罩 ViewGroup扩展一运行时动态更换遮罩形状原库的 XML 配置是静态的但setMask()方法支持运行时热更新。你可以继承MaskableFrameLayout并封装自己的 API比如点击按钮在圆形、星形之间切换// 子类中提供公开方法 public void applyCircleMask() { setMask(R.drawable.masking_masking_01); // 圆形遮罩 } public void applyStarMask() { setMask(R.drawable.masking_masking_20); // 星形遮罩 }注意setMask()内部会自动重建 Bitmap 并调用invalidate()无需手动刷新。扩展二让遮罩动起来——AnimationDrawable 动画遮罩这是本库最亮眼的特性遮罩本身可以是一段逐帧动画。Sample 中的animation_mask.xml是一个包含 60 帧 PNG 的animation-list每帧 18ms源码通过setCallback(this)注册为 View 的 Callback并重写invalidateDrawable()、scheduleDrawable()驱动动画刷新。在你的自定义遮罩 ViewGroup 中可以像 Sample 的MainActivity一样主动触发动画Drawable drawable getDrawableMask(); if (drawable instanceof AnimationDrawable) { AnimationDrawable anim (AnimationDrawable) drawable; anim.stop(); anim.start(); // 遮罩形状开始逐帧变化 }基于这个思路你甚至可以用Animator驱动形状渐变实现「呼吸」或「波纹」等更复杂的动效。扩展三借助 PorterDuff 模式玩出更多视觉效果除了裁剪用的DST_IN库还支持 17 种混合模式attrs_maskable_framelayout.xml中已定义枚举。在扩展时调用setPorterDuffXferMode()即可随时切换setPorterDuffXferMode(PorterDuff.Mode.DST_OUT); // 挖空效果 setPorterDuffXferMode(PorterDuff.Mode.MULTIPLY); // 正片叠底 setPorterDuffXferMode(PorterDuff.Mode.SCREEN); // 滤色提亮比如用DST_OUT实现圆形挖孔配合底层阴影即可做出「异形头像卡片」等高级 UI。自定义遮罩 ViewGroup 时的三个避坑要点坑一必须使用软件层绘制。源码构造方法中调用了setLayerType(LAYER_TYPE_SOFTWARE, null)因为PorterDuffXfermode依赖软件渲染。如果你的自定义 ViewGroup 关闭了软件层遮罩会直接失效——这是最常见的「为什么没效果」原因。坑二宽高为 0 时遮罩静默失败。makeBitmapMask()在宽高不大于 0 时只打日志并返回 null。所以避免在wrap_content且无子 View 的情况下使用并留意日志中的Cant create a mask提示。坑三遮罩 Bitmap 会频繁重建注意内存回收。源码在onSizeChanged时重建遮罩并在swapBitmapMask()中回收旧 Bitmap。扩展时若自行持有遮罩引用务必按相同方式管理防止内存抖动。写在最后从「改一行属性」到「读懂核心源码」android_maskable_layout 是一个非常适合练习自定义 View 的小而美项目。掌握了它的 Bitmap 遮罩 PorterDuff 混合模式这两大核心思想你就拥有了扩展出任意形状、任意动画、任意混合效果的自定义遮罩 ViewGroup 的能力。希望这份完整指南能帮你少踩坑、快上手写出更精致的 Android 界面。【免费下载链接】android_maskable_layoutA library that easily allows you to mask layouts/viewgroups项目地址: https://gitcode.com/gh_mirrors/an/android_maskable_layout创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考