Android Canvas绘制带渐变填充的曲线图形技术求助
嘿,我来帮你搞定这些Canvas绘图的问题!咱们一步步拆解你的需求,逐个解决:
1. 修正后的曲线绘制示例代码及参数解析
先看你原来的代码里,第二个圆弧的RectF超出了Canvas范围(Canvas高度只有300,你设的top是300,直接跑到画布外面去了),所以看不到。我给你调整了位置,还加了贝塞尔曲线的示例,方便你理解不同曲线的绘制方式:
public class DrawingActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_drawing); ImageView img = findViewById(R.id.img); // 创建画布,宽1000,高300 Bitmap bitmap = Bitmap.createBitmap(1000, 300, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawColor(Color.LTGRAY); // 初始化描边画笔 Paint strokePaint = new Paint(); strokePaint.setColor(Color.RED); strokePaint.setStyle(Paint.Style.STROKE); strokePaint.setStrokeWidth(8); strokePaint.setAntiAlias(true); // 绘制第一条直线 int centerY = canvas.getHeight() / 2; canvas.drawLine(0, centerY, 300, centerY, strokePaint); // 绘制第一个圆弧(左上) RectF oval1 = new RectF(250, 100, 300, 200); // 参数:椭圆边界RectF,起始角度,扫过角度,是否连接圆心,画笔 canvas.drawArc(oval1, 90, -90, false, strokePaint); // 绘制第二个圆弧(中间,调整到画布可见范围内) RectF oval2 = new RectF(450, 150, 500, 250); canvas.drawArc(oval2, 90, -90, false, strokePaint); // 绘制二阶贝塞尔曲线(示例复杂曲线) Path bezierPath = new Path(); bezierPath.moveTo(300, centerY); // 曲线起点 bezierPath.quadTo(400, 50, 500, centerY); // 控制点(400,50),终点(500,centerY) strokePaint.setColor(Color.BLUE); canvas.drawPath(bezierPath, strokePaint); // 绘制第二条直线 canvas.drawLine(500, canvas.getHeight() - 50, 1000, canvas.getHeight() - 50, strokePaint); img.setImageBitmap(bitmap); } }
参数解释:
drawLine(startX, startY, stopX, stopY, paint):直接画直线,四个坐标分别是起点和终点的x/y值。drawArc(oval, startAngle, sweepAngle, useCenter, paint):oval:圆弧所在椭圆的边界矩形(后面详细讲)startAngle:起始角度(0°对应3点钟方向,顺时针为正方向)sweepAngle:圆弧扫过的角度(负数表示逆时针方向)useCenter:如果为true,会把圆弧两端和椭圆中心连接,形成扇形;false只画弧本身。
drawPath(path, paint):通过Path对象绘制任意复杂曲线,示例里的quadTo是二阶贝塞尔曲线,需要一个控制点和终点。
2. 彻底搞懂drawArc的left/top/right/bottom参数
你提到的这四个参数是用来定义圆弧所在椭圆的外切矩形的:
left:矩形左侧边缘的x坐标top:矩形顶部边缘的y坐标right:矩形右侧边缘的x坐标bottom:矩形底部边缘的y坐标
举个例子,你原来的oval.set(250, 100, 300,200):
- 矩形的宽度是
300-250=50,高度是200-100=100 - 椭圆会刚好内切于这个矩形,所以是一个“竖长”的椭圆
- 然后drawArc就是在这个椭圆上截取一段弧,角度参数决定了弧的位置和长度
简单说:这四个参数框出了椭圆的范围,椭圆的中心就是(left+right)/2, (top+bottom)/2,椭圆的长轴短轴由矩形的宽高决定。
3. 实现目标图形的渐变填充(仅填充指定图形)
要实现只给单个图形填渐变,核心是给Paint设置Shader,并且让Shader的范围和目标图形匹配。这里以第一个圆弧的渐变填充为例:
// 给第一个圆弧创建渐变填充画笔 Paint fillPaint = new Paint(); fillPaint.setAntiAlias(true); // 创建线性渐变:从矩形左上角到右下角,颜色从红到黄 LinearGradient arcGradient = new LinearGradient( 250, 100, // 渐变起始点x/y(对应oval1的left/top) 300, 200, // 渐变结束点x/y(对应oval1的right/bottom) Color.RED, Color.YELLOW, // 起始和结束颜色 Shader.TileMode.CLAMP // 超出渐变范围时的颜色填充模式 ); fillPaint.setShader(arcGradient); // 绘制带渐变填充的扇形(useCenter设为true) canvas.drawArc(oval1, 90, -90, true, fillPaint);
关键点:
- 渐变的起始/结束坐标要和目标图形的RectF对应,这样渐变才会刚好覆盖图形
- 如果是径向渐变,可以用
RadialGradient,参数是圆心、半径、颜色组 - 一定要把Paint的Style设为
FILL(默认就是FILL,所以不用额外设置,除非之前设过STROKE) - Shader是绑定在Paint上的,所以不同图形需要不同的Paint(或者每次绘制前重新设置Shader)
这样就能实现只给目标图形填充渐变,而不会影响整个Canvas的背景啦!
内容的提问来源于stack exchange,提问作者Annie
相关产品推荐
相关产品推荐

