'How to detect if any part of one view is overlapping another view in android
What I am trying to do: I am trying to determine .... If any part of one view crosses other view
What I have done:
Usage: isDragOverlap = textView.isOverlap(buttonView)
Code:
private fun View.isOverlap(other: View, deltaX: Int = 0, deltaY: Int = 0): Boolean {
val thisXY = IntArray(2).apply { getLocationOnScreen(this) }
val otherXY = IntArray(2).apply { other.getLocationOnScreen(this)
this[0] += deltaX
this[1] += deltaY
}
return thisXY.let {
Rect(it[0], it[1], it[0] + width, it[1] + height)
}
.intersect(otherXY.let {
Rect(it[0], it[1], it[0] + other.width, it[1] + other.height)
}
)
}
Above code works as: Here below intersection is detected
What is not working: Here below intersection is not detected
Solution 1:[1]
I have written the following function and it seems to work. You can try it and let me know if You have found any problems.
private fun View.isOverlap(other: View, deltaX: Int = 0, deltaY: Int = 0): Boolean
{
val rectThis = Rect()
this.getHitRect(rectThis)
rectThis.offset(deltaX, deltaY) //addind delta to every side of Rect
val rectOther = Rect()
other.getHitRect(rectOther)
return rectThis.intersect(rectOther)
}
Main Activity XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/conLay"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/v1"
android:layout_width="149dp"
android:layout_height="114dp"
android:layout_marginStart="164dp"
android:layout_marginTop="64dp"
android:text="v1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/v2"
android:layout_width="126dp"
android:layout_height="114dp"
android:layout_marginTop="160dp"
android:layout_marginEnd="232dp"
android:text="v2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val v1 = findViewById<Button>(R.id.v1)
val v2 = findViewById<Button>(R.id.v2)
v1.setOnClickListener {
Log.d("One - two", v1.isOverlap(v2, 2, 1).toString())
Log.d("Two - one", v2.isOverlap(v1, 1, 2).toString())
}
}
}
private fun View.isOverlap(other: View, deltaX: Int = 0, deltaY: Int = 0): Boolean {
val rectThis = Rect()
this.getHitRect(rectThis)
Log.d("rectThis before change", rectThis.toShortString())
rectThis.offset(deltaX, deltaY)
Log.d("rectThis after change", rectThis.toShortString())
val rectOther = Rect()
other.getHitRect(rectOther)
Log.d("rectOther", rectOther.toShortString())
return rectThis.intersect(rectOther)
}
Solution 2:[2]
This may help you.
fun View.isOverlappedByOtherView(): Boolean {
return isOverlappedByOtherView(Rect().apply { getGlobalVisibleRect(this) })
}
private fun View.isOverlappedByOtherView(viewRect: Rect): Boolean {
val tempParent = parent
if (tempParent is ViewGroup) {
val mIndex = tempParent.indexOfChild(this)
for (childIndex in (mIndex + 1) until tempParent.childCount) {
val siblingView = tempParent.getChildAt(childIndex)
val intersecting =
siblingView != null && siblingView.isShown && intersectedRect(siblingView).let { pair: Pair<Boolean, Rect> ->
pair.first && pair.second.intersects(
viewRect.left,
viewRect.top,
viewRect.right,
viewRect.bottom
)
}
val isParentOverlapped = tempParent.isOverlappedByOtherView(viewRect)
if (intersecting || isParentOverlapped) {
return true
}
}
}
return false
}
fun View.intersectedRect(otherView: View): Pair<Boolean, Rect> {
val viewRect = Rect().apply { getGlobalVisibleRect(this) }
val otherViewRect = Rect().apply { otherView.getGlobalVisibleRect(this) }
val intersects = viewRect.intersect(otherViewRect)
return Pair(intersects, viewRect)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |