前语
在 Android 的界面制作中,控件的暗影是我们经常会处理的一种界面元素,尤其会呈现在按钮 Button 这种需求吸引用户关注点的控件上。Android 原生供给了控件的 Z 轴特点即 elevetion 供暗影作用,可是这个作用嘛,但凡是有一点想法的 UI 都不会满足的,比方我司的,就坚决不接受。
常见的问题比方不支撑特定的暗影形状或巨细,或不允许完全自定义暗影的色彩或透明度,切图是一种办法,可是自定义 View 制作的作用会更好,究竟切图会实实在在的形成 apk 包体积的增大,而且屏幕适配也会是一个潜藏的问题危险。
结合我的经历,简单封装了一下,共享我目前运用的 ShadowView
运用
圆角矩形暗影
-
一般暗影
<?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" tools:context=".MainActivity"> <com.randalldev.shadowview.ShadowView android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="@id/btn_target" app:layout_constraintEnd_toEndOf="@id/btn_target" app:layout_constraintStart_toStartOf="@id/btn_target" app:layout_constraintTop_toTopOf="@id/btn_target" app:shadowBottomHeight="16dp" app:shadowCardColor="#FF7043" app:shadowColor="#FFEE58" app:shadowLeftHeight="16dp" app:shadowRadius="16dp" app:shadowRightHeight="16dp" app:shadowRound="8dp" app:shadowTopHeight="16dp" /> <Button android:id="@+id/btn_target" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" android:paddingStart="40dp" android:paddingEnd="40dp" android:paddingTop="20dp" android:paddingBottom="20dp" android:text="target button" android:textColor="@color/purple_700" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>抛开配色不谈,这个作用还能够吧
-
一般暗影 + 偏移
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout app:shadowLeftHeight="16dp" app:shadowOffsetX="8dp" app:shadowOffsetY="4dp" app:shadowRadius="16dp" </androidx.constraintlayout.widget.ConstraintLayout>
圆形暗影
圆形暗影也能够认为是一种特殊的圆角矩形暗影,能够持续沿用圆角矩形的办法,或许增加 shadowShape 特点。
假如要运用圆角矩形的办法,需求事前确认方针控件的尺度,这可能会遇到屏幕适配问题,所以我这儿就直接演示运用 shadowShape 特点的办法
-
一般暗影
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout app:shadowCardColor="#FF7043" app:shadowColor="#FFEE58" app:shadowRadius="16dp" app:shadowShape="1" /> <Button android:id="@+id/btn_target" android:layout_width="wrap_content" android:layout_height="0dp" android:background="@android:color/transparent" android:padding="20dp" android:text="target button" android:textColor="@color/purple_700" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintDimensionRatio="1:1" </androidx.constraintlayout.widget.ConstraintLayout>很简单吧,相比圆角矩形的配置,多了一个
shadowShape可是少了很多尺度的设置,只需求设置一个shadowRaduis即可。需求留意的是,我这儿运用了
ConstrainLayout的ratio特点设置为1:1来完成一个正方形的方针控件,由于在制作圆形时,是以控件的中心作为圆心来制作的,假如不是正方形就可能呈现问题了。 -
一般暗影 + 偏移
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout app:shadowCardColor="#FF7043" app:shadowColor="#FFEE58" app:shadowRadius="16dp" app:shadowOffsetX="4dp" app:shadowOffsetY="4dp" app:shadowShape="1" /> </androidx.constraintlayout.widget.ConstraintLayout>
这个运用起来仍是比较便利的吧,只需求方针控件设置
padding留出足够的空间制作暗影作用即可。而且不需求再写
drawable文件设置控件的背景了。当然也不是没有缺陷,目前仍是只能兼容圆角矩形和圆形。异形的暂时没用到,可能也不会去做支撑。
完成
什么是暗影
首先,暗影是什么?
在真实世界中,暗影是物体遮挡住光源的光路呈现的现象;在 Android View 系统中则是 Z 轴高度,Z 轴高度越高,暗影范围越大,色彩越深。
可是只是通过 elevetion 特点设置 Z 轴高度完成的暗影视效上往往只能说满足有无的问题,究竟国内谁按照 MD 风格去规划界面啊。
那么,暗影是什么?
当我们自定义 View 去制作暗影的时候,其实也能够是一圈从边际向四周放射式扩散的渐变色层,从而形成一种视觉的暗影作用。
那偏移又是什么?
偏移其实便是表达光源的位置,偏移为 0,即光源在正中心光线直射,暗影作用是从边际均匀的向四周逐渐变淡。
X 偏移为正,则光源在中心偏右,Y 偏移为正,则光源在中心偏下。 若为负数则相反。视觉上则会呈现某一或两轴方向上的暗影区域偏少。
上代码
初始化
这段很简单,便是读取 attrs 特点,设置硬件加速
init {
initView(context, attrs)
//设置软件烘托类型,跟制作暗影相关,后边会说
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
制作暗影
这儿创立了一个画笔 Paint 的实例,画笔的色彩是方针控件的背景色;制作形式设置的是 FILL 表明填充形式,还有 STROKE 描边形式,FILL_AND_STROKE 描边加填充形式;AntiAlias 设置为 true 标识敞开抗锯齿。
这儿便是运用 Paint 的 setShadowLayer() 办法创立暗影作用,其中:
-
radius:暗影半径,值越大暗影越含糊,值为0时暗影消失。 -
dx:暗影在水平方向的偏移量,正值表明向右偏移,负值表明向左偏移。 -
dy:暗影在笔直方向的偏移量,正值表明向下偏移,负值表明向上偏移。 -
shadowColor:暗影色彩。
Canvas 能够理解为画布,根据 shadowShape 特点在画布上对应的制作圆角矩形和圆形两种不同形状。
-
drawRoundRect()用于在Canvas上制作一个圆角矩形。该办法需求传递四个参数,分别是矩形左上角的X坐标,矩形左上角的Y坐标,矩形右下角的X坐标和矩形右下角的Y坐标。此外还需求供给两个额定参数,分别是圆角的X半径和Y半径。 -
canvas.drawCircle()用于在Canvas上制作一个圆形。该办法需求传递三个参数,分别是圆心的X坐标,圆心的Y坐标以及圆的半径。
创立一个 RectF,也便是一个矩形目标,表明一个浮点数精度的矩形。在制作操作,比方指定制作区域、裁剪画布等经常会用到。其结构函数包括4个浮点型成员变量:left、top、right、bottom,分别表明矩形左鸿沟、上鸿沟、右鸿沟和下鸿沟的坐标值。
override fun dispatchDraw(canvas: Canvas) {
// 配置画笔
val shadowPaint = Paint()
shadowPaint.color = shadowCardColor
shadowPaint.style = Paint.Style.FILL
shadowPaint.isAntiAlias = true
val left = shadowLeftHeight.toFloat()
val top = shadowTopHeight.toFloat()
val right = (width - shadowRightHeight).toFloat()
val bottom = (height - shadowBottomHeight).toFloat()
// 配置暗影的范围,偏移,色彩
shadowPaint.setShadowLayer(shadowRadius.toFloat(), shadowOffsetX.toFloat(), shadowOffsetY.toFloat(), shadowColor)
if (shadowShape == 0) {
// 假如制作圆角矩形的暗影,用 drawRoundRect
val rectF = RectF(left, top, right, bottom)
canvas.drawRoundRect(rectF, shadowRound.toFloat(), shadowRound.toFloat(), shadowPaint)
} else {
// 假如制作圆形的暗影,用 drawCircle
val radius = measuredHeight.toFloat() / 2 - shadowRadius
canvas.drawCircle(measuredHeight.toFloat() / 2, measuredHeight.toFloat() / 2, radius, shadowPaint)
}
shadowPaint.utilReset()
canvas.save()
}
总结
在 Android 界面制作中,暗影是常见的 UI 元素之一,而 Android 原生供给的 elevation 特点虽然能够完成暗影作用,但往往不能满足 UI 规划的要求。因此,自定义 View 制作暗影的办法更为灵敏和实用。本文介绍了 ShadowView,它能够便利地制作圆角矩形和圆形的暗影,且支撑色彩、透明度和暗影形状的自定义。此外,本文还供给了运用 ShadowView 制作暗影的示例代码,可供读者参阅和运用。通过运用 ShadowView,能够愈加便利地完成杂乱、美观的暗影作用,提高 Android 使用的用户体会。
参阅文章
Android进阶:快速完成自定义暗影作用
ShadowView





