I have a view(Calendar) that contains multiple Rects(Events) drawn on it, now I am trying to implement drag/drop as another layer on top of that view. Example- I long-press on an event, it passes me the exact coordinates of the Rect(Event), no I have created a custom view which will draw the same Rect(because I have coordinates)
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)
}
}
Now the listener will pass me the coordinates when long-press on an event.
Current situation: I put the above view in the XML(On Top of the calendar View) and just made it visible when I get the coordinates, but don't know how to draw Rect on it because it is already initialized.
If I miss something to provide as information, please let me know in the comments I'll update the question
I have created a custom view which will draw the event on the same coordinates and can move that event
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?)
}
}