在 canvas 上绘制 RectF

Draw RectF on canvas

我有一个视图(日历),其中包含绘制在其上的多个矩形(事件),现在我正在尝试将 drag/drop 实现为该视图之上的另一层。示例-我长按一个事件,它向我传递了 Rect(Event) 的确切坐标,不,我创建了一个自定义视图,它将绘制相同的 Rect(因为我有坐标)

class DraggerView: View {


    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)


    override fun isInEditMode(): Boolean {
        return true
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

    }
}

现在监听器会在长按事件时将坐标传给我。

现状:我把上面的视图放在XML(在日历视图的顶部),当我得到坐标时就让它可见,但是不知道如何在上面画Rect,因为它已经初始化了。

如果我遗漏了一些信息,请在评论中告诉我,我会更新问题

我假设您的日历视图和您将实现的视图大小相同,您可以在 xml 文件中实现它。要在每个位置更改时绘制一个矩形,您可以在自定义视图中创建一个方法 class.

fun onRectTranslated(dx:Int, y:Int){
    mRect.offset(dx,dy)
    postInvalidateOnAnimation()
}

然后在你onDraw()回调:

 override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    canvas?.drawRect(mRect,mRectPaint)
}

在您的初始化阶段,您可以创建 mRect 对象,因为 Rect.Then 您在此矩形上应用更改,然后使视图无效,以便系统再次为您的视图调用 onDraw。此外,您必须为绘图创建一个绘画对象。

我创建了一个自定义视图,它将在同一坐标上绘制事件并可以移动该事件

class DraggerView : View {


    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    private var availableWidth: Int = 0
    private var availableHeight: Int = 0
    private var title: String = ""
    private var rect: RectF? = null
    private val paintEvent = Paint()
    private val paintText: TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG or Paint.LINEAR_TEXT_FLAG).apply {
        isAntiAlias=true
        style = Paint.Style.FILL
        color = Color.WHITE
        textSize = 30f
        typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
    }
    private var data: Event? = null
    private var draw = false
    var eventListener: EventListener? = null

    override fun isInEditMode(): Boolean {
        return true
    }

    @SuppressLint("NewApi")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (draw) {
            canvas.save()
            canvas.drawColor(ContextCompat.getColor(context, R.color.shadow))
            rect?.let { rectF ->
                canvas.drawRoundRect(rectF, 10f, 10f, paintEvent)
                val x = rectF.left + 10
                val y = rectF.top + 10

                val layout = StaticLayout.Builder.obtain(title, 0, title.length, paintText, availableWidth)
                        .setAlignment(Layout.Alignment.ALIGN_NORMAL)
                        .setLineSpacing(0.0f, 1.0f)
                        .setIncludePad(false)
                        .build()
                canvas.translate(x, y)
                layout.draw(canvas)

            }
            canvas.restore()
        }

    }

    fun drawEvent(rectF: RectF, data: Event) {
        draw = true
        rect = rectF
        this.data = data
        title = data.title
        availableWidth = rectF.right.minus(rectF.left).toInt()
        availableHeight = rectF.bottom.minus(rectF.top).toInt()
        paintEvent.color = data.color
        invalidate()
    }


    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        val xMove = event?.x ?: 0f
        val yMove = event?.y ?: 0f
        when (event?.action) {
            MotionEvent.ACTION_UP -> {
                draw = false
                eventListener?.onEventDrop(rect, data)
            }
            MotionEvent.ACTION_MOVE -> {
                val newLeft = xMove - (availableWidth / 2)
                val newTop = yMove - (availableHeight / 2)
                val newRight = xMove + (availableWidth / 2)
                val newBottom = yMove + (availableHeight / 2)

                rect?.let {
                    it.left = newLeft
                    it.top = newTop
                    it.right = newRight
                    it.bottom = newBottom
                }
                // we might needed to scroll weekview when event
                // dragged to right side of the screen
                if (xMove > (width * 0.90)) {
                    eventListener?.onEventScrollRight(rect, data)
                }
                if (xMove < (width * 0.10)) {
                    eventListener?.onEventScrollLeft(rect, data)
                }
            }
        }
        invalidate()
        return draw
    }

    interface EventListener {
        fun onEventDrop(rectF: RectF?, data: Event?)
        fun onEventScrollRight(rectF: RectF?, data: Event?)
        fun onEventScrollLeft(rectF: RectF?, data: Event?)
    }
}