Paint API 之—— 枚举/常量值 及 ShadowLayer 阴影效果
在 Android 的 Paint 类中,枚举和常量值用于控制绘制行为和样式,涵盖了填充模式、线条样式、文本对齐方式等多个方面。ShadowLayer 则是一种特殊的阴影效果,用于为绘制内容(如形状或文本)添加投影,提升视觉层次感。以下将详细介绍 Paint 的主要枚举/常量值以及 ShadowLayer 的使用方法。
Paint 的主要枚举/常量值
Paint 类定义了多个枚举和常量,用于配置绘制样式、行为和效果。以下是常见枚举和常量的概述:
1. Paint.Style(绘制样式)
Paint.Style 枚举定义了绘制内容的填充方式,影响形状或路径的呈现方式。
- 值:
Paint.Style.FILL:填充整个形状(内部填充)。Paint.Style.STROKE:仅绘制形状的边框(描边)。Paint.Style.FILL_AND_STROKE:同时填充内部和描边。- 用途:控制绘制是填充、描边还是两者兼有。例如,绘制实心矩形用
FILL,绘制空心圆用STROKE。 - 代码示例:
paint.setStyle(Paint.Style.FILL); // 填充矩形
canvas.drawRect(50, 50, 150, 100, paint);
2. Paint.Cap(线条端点样式)
Paint.Cap 枚举定义了线条或路径端点的形状,适用于 STROKE 模式。
- 值:
Paint.Cap.BUTT:平直端点(默认,无额外延伸)。Paint.Cap.ROUND:圆形端点(端点为半圆)。Paint.Cap.SQUARE:方形端点(端点延伸半个笔触宽度)。- 用途:常用于线条或路径的起点/终点美化,如绘制圆头线条。
- 代码示例:
paint.setStrokeWidth(10f);
paint.setStrokeCap(Paint.Cap.ROUND); // 圆形端点
canvas.drawLine(50, 50, 150, 50, paint);
3. Paint.Join(线条连接样式)
Paint.Join 枚举定义了路径拐角处的连接样式,适用于 STROKE 模式。
- 值:
Paint.Join.MITER:尖角连接(默认,尖锐拐角)。Paint.Join.ROUND:圆角连接(拐角为圆弧)。Paint.Join.BEVEL:斜面连接(平滑切角)。- 用途:用于多段路径(如折线或多边形)拐角的样式调整。
- 代码示例:
paint.setStrokeWidth(10f);
paint.setStrokeJoin(Paint.Join.ROUND); // 圆角连接
Path path = new Path();
path.moveTo(50, 50);
path.lineTo(100, 100);
path.lineTo(50, 150);
canvas.drawPath(path, paint);
4. Paint.Align(文本对齐方式)
Paint.Align 枚举定义了文本绘制时的对齐方式。
- 值:
Paint.Align.LEFT:文本左对齐(默认)。Paint.Align.CENTER:文本中心对齐。Paint.Align.RIGHT:文本右对齐。- 用途:控制文本相对于绘制起点的水平对齐,常用于
Canvas.drawText。 - 代码示例:
paint.setTextSize(40f);
paint.setTextAlign(Paint.Align.CENTER); // 居中对齐
canvas.drawText("Hello", 100, 100, paint);
5. Paint.FontMetrics(字体度量常量)
Paint.FontMetrics 提供了文本绘制时的垂直度量值,用于精确布局。
- 主要字段:
top:文本最顶部的相对位置(负值)。ascent:基线到文本上边缘的距离(负值)。descent:基线到文本下边缘的距离(正值)。bottom:文本最底部的相对位置(正值)。leading:行间距(通常为 0 或小值)。- 用途:计算文本高度、行间距或对齐位置。
- 代码示例:
Paint.FontMetrics metrics = paint.getFontMetrics();
float textHeight = metrics.descent - metrics.ascent;
6. 其他常量(部分常见标志)
Paint.ANTI_ALIAS_FLAG:开启抗锯齿,平滑边缘(默认推荐开启)。Paint.DITHER_FLAG:开启抖动,优化颜色过渡(适用于低色深设备)。Paint.FILTER_BITMAP_FLAG:开启位图过滤,提升缩放质量。- 代码示例:
paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
ShadowLayer 阴影效果
ShadowLayer 是一种特殊的 Paint 效果,通过 Paint.setShadowLayer(float radius, float dx, float dy, int color) 方法为绘制内容(形状、文本等)添加阴影效果。阴影本质是一个模糊的颜色投影,增强立体感。
参数说明
radius:模糊半径(float),值越大阴影越模糊。设为 0 则禁用阴影。dx:阴影在 X 轴的偏移量(float),正值向右,负值向左。dy:阴影在 Y 轴的偏移量(float),正值向下,负值向上。color:阴影颜色(int),通常为半透明颜色(如Color.argb(128, 0, 0, 0))。
使用场景
- 为文本添加投影(如标题或标签)。
- 为形状(如按钮、卡片)增加立体感。
- 模拟光源效果(结合动画调整 dx/dy)。
注意事项
- 限制:
ShadowLayer不支持硬件加速(API 14+ 默认启用硬件加速),需禁用硬件加速或使用软件渲染(View.setLayerType(View.LAYER_TYPE_SOFTWARE, null))。 - 性能:大半径阴影或复杂路径可能影响性能,建议谨慎使用。
- 兼容性:API 1+ 支持,但硬件加速限制需注意。
- 清除阴影:调用
paint.clearShadowLayer()移除阴影效果。
代码示例
以下是一个自定义 View 示例,展示 ShadowLayer 结合不同 Paint 样式和枚举的效果:
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.view.View;
public class ShadowLayerView extends View {
private Paint paint;
public ShadowLayerView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 禁用硬件加速以支持 ShadowLayer
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1. 带阴影的填充矩形
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
paint.setShadowLayer(10f, 5f, 5f, Color.argb(128, 0, 0, 0)); // 半径10,偏移(5,5),半透明黑
canvas.drawRect(50, 50, 150, 100, paint);
// 2. 带阴影的描边圆形(圆形端点)
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10f);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setColor(Color.RED);
paint.setShadowLayer(8f, 3f, 3f, Color.argb(128, 0, 0, 0));
canvas.translate(0, 150);
canvas.drawCircle(100, 50, 50, paint);
// 3. 带阴影的文本(居中对齐)
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(40f);
paint.setTextAlign(Paint.Align.CENTER);
paint.setColor(Color.BLACK);
paint.setShadowLayer(5f, 2f, 2f, Color.argb(128, 255, 0, 0)); // 红色阴影
canvas.translate(0, 150);
canvas.drawText("Shadow Text", 100, 50, paint);
// 4. 清除阴影并绘制路径(圆角连接)
paint.clearShadowLayer();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setColor(Color.GREEN);
Path path = new Path();
path.moveTo(50, 50);
path.lineTo(100, 100);
path.lineTo(50, 150);
canvas.translate(0, 150);
canvas.drawPath(path, paint);
}
}
- 运行效果:从上到下依次显示带阴影的填充矩形、描边圆形、带红色阴影的文本,以及无阴影的折线路径(圆角连接)。
- 动画扩展:通过动态调整
dx和dy(配合ValueAnimator),可以实现阴影移动效果,模拟光源变化。
扩展:Jetpack Compose 中的等效实现
在 Jetpack Compose 中,ShadowLayer 的效果可以通过 Modifier.shadow 或 drawWithCache 结合 Blur 实现。例如:
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.unit.dp
@Composable
fun ShadowExample() {
Canvas(
modifier = Modifier
.size(200.dp)
.shadow(elevation = 10.dp, shape = RectangleShape) // 添加阴影
) {
drawRect(
color = Color.Blue,
topLeft = Offset(50f, 50f),
size = Size(100f, 50f),
style = Fill
)
}
}
- 说明:
Modifier.shadow提供类似ShadowLayer的效果,支持圆角和偏移调整。复杂阴影(如文本或路径的自定义阴影)需使用drawWithContent和Blur。
注意事项
- 枚举选择:合理选择
Style、Cap和Join能显著提升绘图美观度。例如,ROUND端点和连接适合平滑曲线,MITER适合锐利边角。 - ShadowLayer 性能:禁用硬件加速可能导致性能下降,建议在小范围使用或缓存为
Bitmap。 - 与 Shader/PathEffect 的结合:
ShadowLayer可与Shader(渐变填充)或PathEffect(虚线)组合,创造丰富效果,如带阴影的渐变虚线。 - 调试:Android SDK 的 ApiDemos 包含
Paint相关示例,可参考学习。
如果需要更详细的某枚举用法(如 FontMetrics 的精确布局)、ShadowLayer 的动画实现,或 Compose 中的高级阴影效果,请告诉我!