Search code examples
androidandroid-canvasandroid-custom-viewtouch-event

How can I move a Path object drawn on the canvas?


I have a Custom View that draws a gray rectangle and a black line inside it:

class CustomViewDemo: View {

    private val mRectangleGray = Path()
    private val mLineBlack = Path()

    private lateinit var mRectanglePaint: Paint
    private lateinit var mBarPaint: Paint

    private var marginLeft: Float = 0F
    private var marginBottom: Float = 0F
    private var marginRight: Float = 0F
    private var marginTop: Float = 0F

    private lateinit var mRectSize: RectF
    private lateinit var mLineSize: RectF

    constructor(context: Context?) : super(context) {
        init(null)
    }

    constructor(context: Context?, list: MutableList<String>, timelineWidth: Int) : super(context) {
        init(null)
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init(attrs)
    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init(attrs)
    }

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        mRectanglePaint = Paint()
        mRectanglePaint.isAntiAlias = true
        mRectanglePaint.color = Color.parseColor("#dedede")

        mBarPaint = Paint()
        mBarPaint.style = Paint.Style.FILL
        mBarPaint.color = Color.BLACK
    }

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        drawRectangle(canvas)
        drawVerticalLine(canvas)
    }

    private fun drawRectangle(canvas: Canvas) {
        marginLeft = 50F
        marginRight = width - 50F
        marginTop = 300F
        marginBottom = 450F

        mRectSize = RectF(marginLeft, marginTop, marginRight, marginBottom)
        mRectangleGray.addRect(mRectSize, Path.Direction.CW)

        canvas.drawPath(mRectangleGray, mRectanglePaint)
    }

    private fun drawVerticalLine(canvas: Canvas) {
        marginLeft = 50F
        marginRight = width - 50F
        marginTop = 300F
        marginBottom = 450F

        mLineSize = RectF(marginRight - 7, marginTop, marginRight, marginBottom)
        mLineBlack.addRect(mLineSize, Path.Direction.CW)

        canvas.drawPath(mLineBlack, mBarPaint)
    }

}

Output:

enter image description here

I want to move black line to right and left by touching within the borders of the gray rectangle.

However, I couldn't do this with onTouchEvent. , Drag and move a circle drawn on canvas I tried to adapt it according to the answer to this question, but instead of lines, I started drawing different black dots. Maybe I did something wrong I don't know but I tried so many times.

How can I move a Path object drawn on the canvas to the right and left in the rectangle by touching it? Thank you.


Solution

  • This won't give you exactly what you need, but it should be enough to get you on the right track.

    Add the following onTouchEvent handler to your custom view:

    private var linePositionOffset = 0f  
    private var startX = width - 7  
      
    override fun onTouchEvent(event: MotionEvent): Boolean {  
        val eventAction = event.action  
      
      val x = event.x.toInt()  
      when (eventAction) {  
            MotionEvent.ACTION_DOWN -> {  
                startX = x  
            }  
            MotionEvent.ACTION_UP -> {}  
            MotionEvent.ACTION_MOVE -> {  
                linePositionOffset = (startX - x).toFloat()  
            }  
      }  
      
        // tell the View to redraw the Canvas  
      invalidate()  
      
        // tell the View that we handled the event  
      return true  
    }
    

    And change onDraw() to this:

    override fun onDraw(canvas: Canvas) {  
        drawRectangle(canvas)  
        canvas.withTranslation(-linePositionOffset, 0f) {  
           drawVerticalLine(canvas)  
        }  
    }
    

    enter image description here