Как ОТМЕНИТЬ / REDO формы, нарисованные на холсте в android - PullRequest
0 голосов
/ 15 апреля 2020

Я являюсь промежуточным звеном в android разработке, и мне дали модуль приложения, который включает в себя все операции холста, т.е. свободный рисунок, фигуры и текст. Я сделал со свободным рисунком и его операциями отмены / возврата. Но я не могу понять, как отменить повторяющиеся фигуры, нарисованные на холсте. Когда я использую методы: canvas.drawRect (args), то же самое происходит и в случае круга, ar c et c, но я не могу удалить их с холста. Если я использую 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 голосов
/ 22 апреля 2020

Вы можете добавить путь в TOUCH_START и добавить фигуры в этом пути в ACTION_MOVE и сбросить кординаты в TOUCH_UP, например:

TOUCH_DOWN:

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

TOUCH_MOVE :

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)

TOUCH_DOWN:

if (isDown) {
        startX = 0F
        startY = 0F
        isDown = false
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...