You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android绘图应用无法在Canvas上绘图问题求助

绘图应用无法在Canvas上绘图的解决方案

你的代码存在三个关键问题,导致无法正常在Canvas上绘图,下面逐一说明并给出修复方案:

问题1:onDraw方法绘制逻辑错误

原代码在onDraw中错误地将缓存Bitmap绘制到自己创建的myCanvas,而非系统传入的用于显示到屏幕的canvas参数。正确逻辑应该是:把缓存的Bitmap绘制到屏幕的canvas,同时将当前路径绘制到缓存Bitmap的myCanvas,这样后续绘制才能保留历史内容。

问题2:ACTION_DOWN事件中坐标错误

触摸按下的处理里,moveTo方法错误传入两次touchX,导致起点Y坐标异常,应传入touchX和touchY。

问题3:未保存历史绘制路径

每次触摸抬起时直接新建CustomPath,之前绘制的路径会完全丢失,需要维护一个列表保存所有完成的路径,onDraw时遍历绘制所有历史路径。

修复后的DrawingView.kt代码

package com.example.drawingapp

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View

class DrawingView(context: Context, attrs: AttributeSet) : View(context, attrs) {

    private var myDrawPath: CustomPath? = null
    private var myCanvasBitmap: Bitmap? = null
    private var myDrawPaint: Paint? = null
    private var myCanvasPaint: Paint? = null
    private var myCanvas: Canvas? = null
    // 新增历史路径列表,保存已完成的绘制路径
    private val pathList = ArrayList<CustomPath>()

    private var myBrushSize: Float = 0.toFloat()
    private var myColor = Color.BLACK

    init {
        drawingSetUp()
    }

    private fun drawingSetUp() {
        myDrawPaint = Paint()
        myDrawPath = CustomPath(myColor, myBrushSize)
        myDrawPaint!!.color = myColor
        myDrawPaint!!.style = Paint.Style.STROKE
        myDrawPaint!!.strokeJoin = Paint.Join.ROUND
        myDrawPaint!!.strokeCap = Paint.Cap.ROUND
        myCanvasPaint = Paint(Paint.DITHER_FLAG)
        myBrushSize = 20.toFloat()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        myCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
        myCanvas = Canvas(myCanvasBitmap!!)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 将缓存的Bitmap绘制到屏幕的canvas上
        canvas.drawBitmap(myCanvasBitmap!!, 0f, 0f, myCanvasPaint)

        // 绘制所有历史路径到缓存Bitmap
        for (path in pathList) {
            myDrawPaint!!.strokeWidth = path.brushThickness
            myDrawPaint!!.color = path.color
            myCanvas!!.drawPath(path, myDrawPaint!!)
        }

        // 绘制当前正在绘制的路径到屏幕
        if (!myDrawPath!!.isEmpty) {
            myDrawPaint!!.strokeWidth = myDrawPath!!.brushThickness
            myDrawPaint!!.color = myDrawPath!!.color
            canvas.drawPath(myDrawPath!!, myDrawPaint!!)
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        val touchX = event?.x ?: return false
        val touchY = event?.y ?: return false

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                myDrawPath!!.color = myColor
                myDrawPath!!.brushThickness = myBrushSize
                myDrawPath!!.reset()
                // 修正坐标参数,使用touchX和touchY
                myDrawPath!!.moveTo(touchX, touchY)
            }
            MotionEvent.ACTION_MOVE -> {
                myDrawPath!!.lineTo(touchX, touchY)
            }
            MotionEvent.ACTION_UP -> {
                // 将完成的路径加入历史列表
                pathList.add(myDrawPath!!)
                // 新建路径用于下一次绘制
                myDrawPath = CustomPath(myColor, myBrushSize)
            }
            else -> return false
        }
        invalidate()
        return true
    }

    internal inner class CustomPath(var color: Int, var brushThickness: Float) : Path()
}

其他文件说明

activity_main.xml和MainActivity.kt无需修改,当前配置是正确的。

内容的提问来源于stack exchange,提问作者Amandeep Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:24:26