如何在Android的画布上撤消/重做形状

时间:2020-04-15 08:35:47

标签: android kotlin

我是android开发的中级人员,为我提供了一个应用程序模块,其中包含画布的所有操作,即自由绘图,形状和文本。我已经完成了免费绘图及其撤消/重做操作。但是我不知道如何撤消在画布上绘制的重做形状。 当我使用以下方法时:canvas.drawRect(args)在圆形,弧形等情况下都可以正常使用,但是我无法从画布中删除它们。 如果我使用Path.addRect(args)并绘制onDraw(),则在我脱开手指以拖动时进行绘制时,形状不会呈现,然后出现形状。 下面是我的DrawView类: 提前致谢!

class DrawView(context: Context, attrs: AttributeSet?) : View(context, attrs) {


    companion object {
        val TYPE_LINE = 0
        val TYPE_RECT = 1
        val TYPE_CIRCLE = 2
    }

    val DEFAULT_BG_COLOR = Color.WHITE

    private var startX = 0f
    private var startY = 0f
    private var endX = 0f
    private var endY = 0f
    private var drawType: Int = 0
    private val TOUCH_TOLERANCE = 4f
    private var mX = 0f
    private var mY: Float = 0f
    private var mPath: Path? = null
    private var mPaint: Paint? = null
    private var currentColor = Color.BLUE
    private var defaultBgColor = DEFAULT_BG_COLOR
    private var strokeWidth = 10f
    private var mBitmap: Bitmap? = null
    private var mCanvas: Canvas? = null
    private val mBitmapPaint = Paint(Paint.DITHER_FLAG)

    private val paths: ArrayList<PathHolder> = ArrayList()
    private val undo: ArrayList<PathHolder> = ArrayList()

    init {
        mPaint = Paint()
        mPaint!!.isAntiAlias = true
        mPaint!!.isDither = true
        mPaint!!.color = currentColor
        mPaint!!.style = Paint.Style.STROKE
        mPaint!!.strokeJoin = Paint.Join.ROUND
        mPaint!!.strokeCap = Paint.Cap.ROUND
        mPaint!!.xfermode = null
        mPaint!!.alpha = 0xff
    }

    fun initialise(displayMetrics: DisplayMetrics) {
        val height = displayMetrics.heightPixels
        val width = displayMetrics.widthPixels
        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        mCanvas = Canvas(mBitmap!!)
    }

    override fun onDraw(canvas: Canvas) {
        canvas.save()
        mCanvas!!.drawColor(defaultBgColor)

        for (draw in paths) {
            mPaint!!.color = draw.color 
            mPaint!!.strokeWidth = draw.strokeWidth
            mPaint!!.maskFilter = null
            mCanvas!!.drawPath(draw.path, mPaint!!)
        }

        when(drawType){
            TYPE_RECT -> onDrawRectangle()
            TYPE_CIRCLE -> onDrawCircle()
        }

        canvas.drawBitmap(mBitmap!!, 0f, 0f, mBitmapPaint)
        canvas.restore()
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                touchStart(x, y)
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
                touchUp()
                invalidate()
            }
            MotionEvent.ACTION_MOVE -> {
                touchMove(x, y)
                invalidate()
            }
        }
        return true
    }

    private fun touchStart(x: Float, y: Float) {
        startX = x ; startY = y
        mPath = Path()
        val path = PathHolder(currentColor, strokeWidth, mPath!!)
        paths.add(path)
        mPath!!.reset()
        mPath!!.moveTo(x, y)
        mX = x
        mY = y
    }

    private fun touchMove(x: Float, y: Float) {
        endX = x ; endY = y
        val dx = abs(x - mX)
        val dy: Float = abs(y - mY)
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            if ( drawType == TYPE_LINE )
                mPath!!.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2)
            mX = x
            mY = y
        }
    }

    private fun touchUp() {
        if ( drawType == TYPE_LINE )
            mPath!!.lineTo(mX, mY)
        /*val path = Path()
        path.addRect(startX, startY, endX, endY, Path.Direction.CW)
        paths.add(PathHolder( currentColor, strokeWidth, path ))
        Toast.makeText(context, "${paths.size}", Toast.LENGTH_SHORT).show()*/
    }

    fun clear() {
        paths.clear()
        invalidate()
    }

    fun undo() {
        if (paths.size > 0) {
            undo.add(paths.removeAt(paths.size - 1))
            invalidate() // add
        } else {
            Toast.makeText(context, "Nothing to undo", Toast.LENGTH_LONG).show()
        }
    }

    fun redo() {
        if (undo.size > 0) {
            paths.add(undo.removeAt(undo.size - 1))
            invalidate() // add
        } else {
            Toast.makeText(context, "Nothing to undo", Toast.LENGTH_LONG).show()
        }
    }

    fun setStrokeWidth(width: Float) {
        strokeWidth = width
    }

    fun setColor(color: Int) {
        currentColor = color
    }

    fun setDrawType(drawType: Int) {
        this.drawType = drawType
    }

    private fun onDrawCircle() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mCanvas!!.drawArc(startX, startY, endX, endY, 360f, 360f, false, mPaint!!)
        }else {
            Toast.makeText(context, "not available in Android:${Build.VERSION.SDK_INT}", Toast.LENGTH_SHORT).show()
        }
    }

    private fun onDrawRectangle() {
        mCanvas!!.drawRect(startX, startY, endX, endY, mPaint!!)
    }
}

1 个答案:

答案 0 :(得分:0)

您可以在accept中添加路径,并在TOUCH_START中添加路径形状,并在ACTION_MOVE中重置坐标,如:

TOUCH_DOWN:

TOUCH_UP

TOUCH_MOVE:

mPath = Path()
    mPath!!.moveTo(startX, startY)
    val path = PathHolder(currentColor, currentFillColor, strokeWidth, mPath!!)
    paths.add(path)
    isDown = true

TOUCH_DOWN:

mPath!!.reset()
                val left = min(startX, endX)
                val right = max(startX, endX)
                val top = min(startY, endY)
                val bottom = max(startY, endY)
                mPath!!.addRect(left, top, right, bottom, Path.Direction.CCW)
相关问题