diff --git a/tests/test-home/.androidide/init/model.jar b/tests/test-home/.androidide/init/model.jar
index 0beeb8893..a09b2ff18 100644
Binary files a/tests/test-home/.androidide/init/model.jar and b/tests/test-home/.androidide/init/model.jar differ
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/drag/WidgetDragListener.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/drag/WidgetDragListener.kt
index 77e37ba2e..7057902b8 100644
--- a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/drag/WidgetDragListener.kt
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/drag/WidgetDragListener.kt
@@ -22,11 +22,12 @@ import android.view.View
import android.view.ViewGroup
import com.itsaky.androidide.inflater.IView
import com.itsaky.androidide.inflater.IViewGroup
-import com.itsaky.androidide.inflater.internal.ViewAdapterIndex.getAdapter
import com.itsaky.androidide.inflater.internal.LayoutFile
-import com.itsaky.androidide.inflater.internal.ViewImpl
+import com.itsaky.androidide.inflater.internal.ViewAdapterIndex.getAdapter
import com.itsaky.androidide.inflater.internal.utils.ViewFactory.generateLayoutParams
import com.itsaky.androidide.uidesigner.fragments.DesignerWorkspaceFragment.Companion.DRAGGING_WIDGET_MIME
+import com.itsaky.androidide.uidesigner.models.UiView
+import com.itsaky.androidide.uidesigner.models.UiViewGroup
import com.itsaky.androidide.uidesigner.models.UiWidget
import java.io.File
@@ -35,10 +36,14 @@ import java.io.File
*
* @author Akash Yadav
*/
-class WidgetDragListener(val view: IViewGroup, private val placeholderView: View) :
+internal class WidgetDragListener(val view: UiViewGroup, private val placeholderView: View) :
View.OnDragListener {
- private val placeholder by lazy { ViewImpl(LayoutFile(File(""), ""), "", placeholderView).also { it.includeInIndexComputation = false } }
+ private val placeholder by lazy {
+ UiView(LayoutFile(File(""), ""), "", placeholderView).also {
+ it.includeInIndexComputation = false
+ }
+ }
override fun onDrag(v: View, event: DragEvent): Boolean {
return when (event.action) {
@@ -52,7 +57,7 @@ class WidgetDragListener(val view: IViewGroup, private val placeholderView: View
}
placeholder.removeFromParent()
val state = event.localState
- if (state is ViewImpl) {
+ if (state is UiView) {
state.includeInIndexComputation = false
}
val index = view.computeViewIndex(event.x, event.y)
@@ -71,7 +76,7 @@ class WidgetDragListener(val view: IViewGroup, private val placeholderView: View
data
}
is UiWidget ->
- data.createView(view.viewGroup.context, (view as ViewImpl).file).apply {
+ data.createView(view.viewGroup.context, view.file).apply {
this.view.layoutParams =
generateLayoutParams(this@WidgetDragListener.view.viewGroup)
val adapter = getAdapter(this.name)
@@ -87,7 +92,7 @@ class WidgetDragListener(val view: IViewGroup, private val placeholderView: View
this.view.onHighlightStateUpdated(false)
child.onHighlightStateUpdated(false)
- if (child is ViewImpl) {
+ if (child is UiView) {
child.includeInIndexComputation = true
}
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/DesignerWorkspaceFragment.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/DesignerWorkspaceFragment.kt
index cfbb1b352..f9c150d12 100644
--- a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/DesignerWorkspaceFragment.kt
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/fragments/DesignerWorkspaceFragment.kt
@@ -26,18 +26,22 @@ import androidx.fragment.app.viewModels
import com.blankj.utilcode.util.SizeUtils
import com.itsaky.androidide.fragments.BaseFragment
import com.itsaky.androidide.inflater.IInflateEventsListener
+import com.itsaky.androidide.inflater.IInflationEvent
import com.itsaky.androidide.inflater.ILayoutInflater
import com.itsaky.androidide.inflater.IView
import com.itsaky.androidide.inflater.IViewGroup
import com.itsaky.androidide.inflater.IViewGroup.SingleOnHierarchyChangeListener
import com.itsaky.androidide.inflater.OnInflateViewEvent
import com.itsaky.androidide.inflater.internal.LayoutFile
-import com.itsaky.androidide.inflater.internal.ViewGroupImpl
+import com.itsaky.androidide.inflater.internal.ViewImpl
+import com.itsaky.androidide.inflater.viewGroup
import com.itsaky.androidide.uidesigner.R
import com.itsaky.androidide.uidesigner.UIDesignerActivity
import com.itsaky.androidide.uidesigner.databinding.FragmentDesignerWorkspaceBinding
import com.itsaky.androidide.uidesigner.databinding.LayoutDesignerErrorBinding
import com.itsaky.androidide.uidesigner.drag.WidgetDragListener
+import com.itsaky.androidide.uidesigner.models.UiView
+import com.itsaky.androidide.uidesigner.models.UiViewGroup
import com.itsaky.androidide.uidesigner.utils.WidgetTouchListener
import com.itsaky.androidide.uidesigner.utils.bgDesignerView
import com.itsaky.androidide.uidesigner.utils.layeredForeground
@@ -68,7 +72,7 @@ class DesignerWorkspaceFragment : BaseFragment() {
}
private val workspaceView by lazy {
- object : ViewGroupImpl(LayoutFile(File(""), ""), "", binding!!.workspace) {}
+ UiViewGroup(LayoutFile(File(""), ""), "", binding!!.workspace)
}
companion object {
@@ -79,9 +83,19 @@ class DesignerWorkspaceFragment : BaseFragment() {
}
private val inflateListener by lazy {
- IInflateEventsListener { event ->
- if (event is OnInflateViewEvent) {
- setupView(event.data)
+ object : IInflateEventsListener {
+ override fun onEvent(event: IInflationEvent<*>) {
+ if (event is OnInflateViewEvent) {
+ setupView(event.data)
+ }
+ }
+
+ override fun onInterceptCreateView(view: IView): IView {
+ view as ViewImpl
+ if (view is IViewGroup) {
+ return UiViewGroup(view.file, view.name, view.viewGroup)
+ }
+ return UiView(view.file, view.name, view.view)
}
}
}
@@ -134,19 +148,23 @@ class DesignerWorkspaceFragment : BaseFragment() {
val fg = view.view.foreground
view.view.foreground =
if (fg != null) layeredForeground(requireContext(), fg) else bgDesignerView(view.view.context)
-
+
if (view is IViewGroup) {
- view.view.setOnDragListener(WidgetDragListener(view, placeholder))
- view.addOnHierarchyChangeListener(
- object : SingleOnHierarchyChangeListener() {
- override fun onViewAdded(group: IViewGroup, view: IView) {
- setupView(view)
- }
- }
- )
+ setupViewGroup(view as UiViewGroup)
}
}
+ private fun setupViewGroup(viewGroup: UiViewGroup) {
+ viewGroup.view.setOnDragListener(WidgetDragListener(viewGroup, placeholder))
+ viewGroup.addOnHierarchyChangeListener(
+ object : SingleOnHierarchyChangeListener() {
+ override fun onViewAdded(group: IViewGroup, view: IView) {
+ setupView(view as UiView)
+ }
+ }
+ )
+ }
+
fun setupFromBundle(bundle: Bundle?) {
bundle?.let {
val path = it.getString(UIDesignerActivity.EXTRA_FILE) ?: return
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/CommonUiView.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/CommonUiView.kt
new file mode 100644
index 000000000..fbeca457c
--- /dev/null
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/CommonUiView.kt
@@ -0,0 +1,28 @@
+/*
+ * This file is part of AndroidIDE.
+ *
+ * AndroidIDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AndroidIDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AndroidIDE. If not, see .
+ */
+
+package com.itsaky.androidide.uidesigner.models
+
+/**
+ * Extension properties for [UiView] and [UiViewGroup]
+ *
+ * @author Akash Yadav
+ */
+interface CommonUiView {
+
+ var includeInIndexComputation: Boolean
+}
\ No newline at end of file
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/CommonUiViewImpl.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/CommonUiViewImpl.kt
new file mode 100644
index 000000000..80e3c8299
--- /dev/null
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/CommonUiViewImpl.kt
@@ -0,0 +1,27 @@
+/*
+ * This file is part of AndroidIDE.
+ *
+ * AndroidIDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AndroidIDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AndroidIDE. If not, see .
+ */
+
+package com.itsaky.androidide.uidesigner.models
+
+/**
+ * Implementation of [CommonUiView].
+ *
+ * @author Akash Yadav
+ */
+class CommonUiViewImpl : CommonUiView {
+ override var includeInIndexComputation: Boolean = true
+}
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/RootViewImpl.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/UiView.kt
similarity index 73%
rename from uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/RootViewImpl.kt
rename to uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/UiView.kt
index 3d110ce9c..2c7d4a4b1 100644
--- a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/RootViewImpl.kt
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/UiView.kt
@@ -17,14 +17,15 @@
package com.itsaky.androidide.uidesigner.models
-import android.view.ViewGroup
+import android.view.View
+import com.itsaky.androidide.inflater.IView
import com.itsaky.androidide.inflater.internal.LayoutFile
-import com.itsaky.androidide.inflater.internal.SingleChildViewGroup
+import com.itsaky.androidide.inflater.internal.ViewImpl
/**
- * Root view includes the inflated XML layout.
+ * Extension of [IView] for the UI Designer.
*
* @author Akash Yadav
*/
-class RootViewImpl(file: LayoutFile, name: String, view: ViewGroup) :
- SingleChildViewGroup(file, name, view)
+internal open class UiView(file: LayoutFile, name: String, view: View) :
+ ViewImpl(file, name, view), CommonUiView by CommonUiViewImpl()
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/UiViewGroup.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/UiViewGroup.kt
new file mode 100644
index 000000000..e933de166
--- /dev/null
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/models/UiViewGroup.kt
@@ -0,0 +1,142 @@
+/*
+ * This file is part of AndroidIDE.
+ *
+ * AndroidIDE is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AndroidIDE is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AndroidIDE. If not, see .
+ */
+
+package com.itsaky.androidide.uidesigner.models
+
+import android.graphics.RectF
+import android.view.ViewGroup
+import com.itsaky.androidide.inflater.IView
+import com.itsaky.androidide.inflater.IViewGroupAdapter
+import com.itsaky.androidide.inflater.LayoutBehavior.HORIZONTAL
+import com.itsaky.androidide.inflater.LayoutBehavior.TOP_LEFT
+import com.itsaky.androidide.inflater.LayoutBehavior.VERTICAL
+import com.itsaky.androidide.inflater.internal.LayoutFile
+import com.itsaky.androidide.inflater.internal.ViewAdapterIndex
+import com.itsaky.androidide.inflater.internal.ViewGroupImpl
+
+/**
+ * Extension of [IView] for the UI Designer.
+ *
+ * @author Akash Yadav
+ */
+internal class UiViewGroup(file: LayoutFile, name: String, view: ViewGroup) :
+ ViewGroupImpl(file, name, view), CommonUiView by CommonUiViewImpl() {
+
+ /**
+ * Finds the index of the view based on the touch location.
+ *
+ * @param x The x coordinate.
+ * @param y The y coordinate.
+ * @return The index where the new child should be added. This index must be valid.
+ */
+ fun computeViewIndex(x: Float, y: Float): Int {
+ if (childCount == 0) {
+ return 0
+ }
+ val adapter =
+ ViewAdapterIndex.getAdapter(name) as? IViewGroupAdapter
+ ?: throw IllegalStateException("No view adapter for '$name'")
+ return when (adapter.getLayoutBehavior(this)) {
+ TOP_LEFT -> childCount
+ VERTICAL -> computeViewIndexVertically(x, y)
+ HORIZONTAL -> computeViewIndexHorizontally(x, y)
+ }
+ }
+
+ private fun computeViewIndexHorizontally(x: Float, y: Float): Int {
+ get(0).apply {
+ val rect = getViewRect(this)
+ if (x < rect.left) {
+ return 0
+ }
+ }
+ get(childCount - 1).apply {
+ val rect = getViewRect(this)
+ if (x > rect.right) {
+ return childCount
+ }
+ }
+ val (child, index) = findNearestChild(x, y, false) ?: return childCount
+ val rect = getViewRect(child)
+ val mid = rect.left + (rect.width() / 2)
+ val left = RectF(rect).apply { this.right = mid - 10 }
+ val right = RectF(rect).apply { this.left = mid + 10 }
+ if (x > left.left && x < left.right) {
+ return index - 1
+ }
+ if (x > right.left && x < right.right) {
+ return index + 1
+ }
+ return index
+ }
+
+ private fun computeViewIndexVertically(x: Float, y: Float): Int {
+ get(0).apply {
+ val rect = getViewRect(this)
+ if (y < rect.top) {
+ return 0
+ }
+ }
+ get(childCount - 1).apply {
+ val rect = getViewRect(this)
+ if (y > rect.bottom) {
+ return childCount
+ }
+ }
+ val (child, index) = findNearestChild(x, y, true) ?: return childCount
+ val rect = getViewRect(child)
+ val mid = rect.top + (rect.height() / 2)
+ val top = RectF(rect).apply { this.bottom = mid - 10 }
+ val bottom = RectF(rect).apply { this.top = mid + 10 }
+ if (y > top.top && y < top.bottom) {
+ return index - 1
+ }
+ if (y > bottom.top && y < bottom.bottom) {
+ return index + 1
+ }
+ return index
+ }
+
+ private fun findNearestChild(x: Float, y: Float, vertical: Boolean = true): Pair? {
+ for (i in 0 until childCount) {
+ val child = get(i) as UiView
+ if (!child.includeInIndexComputation) {
+ continue
+ }
+ val rect = getViewRect(child)
+ if (vertical && (y > rect.top && y < rect.bottom)) {
+ return child to i
+ }
+
+ if (!vertical && (x > rect.left && x < rect.right)) {
+ return child to i
+ }
+ }
+
+ return null
+ }
+
+ private fun getViewRect(view: IView): RectF {
+ val v = view.view
+ val rect = RectF()
+ rect.left = v.left.toFloat()
+ rect.top = v.top.toFloat()
+ rect.right = rect.left + v.width
+ rect.bottom = rect.top + v.height
+ return rect
+ }
+}
diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/utils/WidgetTouchListener.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/utils/WidgetTouchListener.kt
index a1c233dff..cb80ab35a 100644
--- a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/utils/WidgetTouchListener.kt
+++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/utils/WidgetTouchListener.kt
@@ -33,7 +33,7 @@ import com.itsaky.androidide.uidesigner.fragments.DesignerWorkspaceFragment
*
* @author Akash Yadav
*/
-class WidgetTouchListener(private val view: IView, context: Context) : OnTouchListener {
+internal class WidgetTouchListener(private val view: IView, context: Context) : OnTouchListener {
private var touchedView: View? = null
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/ForwardingViewGroup.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/ForwardingViewGroup.kt
index 56ba8b9d6..1eca1e885 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/ForwardingViewGroup.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/ForwardingViewGroup.kt
@@ -24,4 +24,4 @@ import com.itsaky.androidide.inflater.IViewGroup
*
* @author Akash Yadav
*/
-class ForwardingViewGroup(val src: IViewGroup) : IViewGroup by src
+open class ForwardingViewGroup(val src: IViewGroup) : IViewGroup by src
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/IViewGroup.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/IViewGroup.kt
index 6a8d46cad..3749a9581 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/IViewGroup.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/IViewGroup.kt
@@ -87,15 +87,6 @@ interface IViewGroup : IView {
return -1
}
- /**
- * Finds the index of the view based on the touch location.
- *
- * @param x The x coordinate.
- * @param y The y coordinate.
- * @return The index where the new child should be added. This index must be valid.
- */
- fun computeViewIndex(x: Float, y: Float): Int
-
/**
* Adds the given hierarchy change listener.
*
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/inflationEvents.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/inflationEvents.kt
index 5a05c5a21..27ab1b48e 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/inflationEvents.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/inflationEvents.kt
@@ -22,7 +22,7 @@ package com.itsaky.androidide.inflater
*
* @author Akash Yadav
*/
-fun interface IInflateEventsListener {
+interface IInflateEventsListener {
/**
* Called when an event occurs. The [event] parameter contains more information about the event.
@@ -30,6 +30,15 @@ fun interface IInflateEventsListener {
* @param event The event.
*/
fun onEvent(event: IInflationEvent<*>)
+
+ /**
+ * Allows the listener to intercept the view creation event and return view instance of their own.
+ *
+ * @param view The view that was created. The properties of this view is not expected to be
+ * modified (see [OnInflateViewEvent] instead).
+ * @return The view that should replace the [view] instance.
+ */
+ fun onInterceptCreateView(view: IView): IView = view
}
/**
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ForwardingView.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ForwardingView.kt
index 7d156f78c..ed1977936 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ForwardingView.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ForwardingView.kt
@@ -24,4 +24,4 @@ import com.itsaky.androidide.inflater.IView
*
* @author Akash Yadav
*/
-class ForwardingView(val src: IView) : IView by src
+open class ForwardingView(protected open val src: IView) : IView by src
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/LayoutInflaterImpl.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/LayoutInflaterImpl.kt
index 4da72b9e4..505bfeaf0 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/LayoutInflaterImpl.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/LayoutInflaterImpl.kt
@@ -282,10 +282,10 @@ open class LayoutInflaterImpl : ILayoutInflater() {
): IView {
return try {
val v = createViewInstance(widget.qualifiedName, parent.context)
- if (v is ViewGroup) {
- return ViewGroupImpl(currentLayoutFile, widget.qualifiedName, v)
- }
- return ViewImpl(currentLayoutFile, widget.qualifiedName, v)
+ val view = if (v is ViewGroup) {
+ ViewGroupImpl(currentLayoutFile, widget.qualifiedName, v)
+ } else ViewImpl(currentLayoutFile, widget.qualifiedName, v)
+ return inflationEventListener?.onInterceptCreateView(view) ?: view
} catch (err: Throwable) {
onCreateUnsupportedView("Unable to create view for widget ${widget.qualifiedName}", parent)
}
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewGroupImpl.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewGroupImpl.kt
index 50a1b9bee..57eef227f 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewGroupImpl.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewGroupImpl.kt
@@ -83,93 +83,6 @@ open class ViewGroupImpl(file: LayoutFile, name: String, view: ViewGroup) :
}
}
- override fun computeViewIndex(x: Float, y: Float): Int {
- if (childCount == 0) {
- return 0
- }
- val adapter =
- ViewAdapterIndex.getAdapter(name) as? IViewGroupAdapter
- ?: throw IllegalStateException("No view adapter for '$name'")
- return when (adapter.getLayoutBehavior(this)) {
- TOP_LEFT -> childCount
- VERTICAL -> computeViewIndexVertically(x, y)
- HORIZONTAL -> computeViewIndexHorizontally(x, y)
- }
- }
-
- private fun computeViewIndexHorizontally(x: Float, y: Float): Int {
- get(0).apply {
- val rect = getViewRect(this)
- if (x < rect.left) {
- return 0
- }
- }
- get(childCount - 1).apply {
- val rect = getViewRect(this)
- if (x > rect.right) {
- return childCount
- }
- }
- val (child, index) = findNearestChild(x, y, false) ?: return childCount
- val rect = getViewRect(child)
- val mid = rect.left + (rect.width() / 2)
- val left = RectF(rect).apply { this.right = mid - 10 }
- val right = RectF(rect).apply { this.left = mid + 10 }
- if (x > left.left && x < left.right) {
- return index - 1
- }
- if (x > right.left && x < right.right) {
- return index + 1
- }
- return index
- }
-
- private fun computeViewIndexVertically(x: Float, y: Float): Int {
- get(0).apply {
- val rect = getViewRect(this)
- if (y < rect.top) {
- return 0
- }
- }
- get(childCount - 1).apply {
- val rect = getViewRect(this)
- if (y > rect.bottom) {
- return childCount
- }
- }
- val (child, index) = findNearestChild(x, y, true) ?: return childCount
- val rect = getViewRect(child)
- val mid = rect.top + (rect.height() / 2)
- val top = RectF(rect).apply { this.bottom = mid - 10 }
- val bottom = RectF(rect).apply { this.top = mid + 10 }
- if (y > top.top && y < top.bottom) {
- return index - 1
- }
- if (y > bottom.top && y < bottom.bottom) {
- return index + 1
- }
- return index
- }
-
- private fun findNearestChild(x: Float, y: Float, vertical: Boolean = true): Pair? {
- for (i in 0 until childCount) {
- val child = get(i) as ViewImpl
- if (!child.includeInIndexComputation) {
- continue
- }
- val rect = getViewRect(child)
- if (vertical && (y > rect.top && y < rect.bottom)) {
- return child to i
- }
-
- if (!vertical && (x > rect.left && x < rect.right)) {
- return child to i
- }
- }
-
- return null
- }
-
override fun addOnHierarchyChangeListener(listener: OnHierarchyChangeListener) {
this.hierarchyChangeListeners.add(listener)
}
@@ -185,26 +98,4 @@ open class ViewGroupImpl(file: LayoutFile, name: String, view: ViewGroup) :
protected open fun notifyOnViewRemoved(child: IView) {
this.hierarchyChangeListeners.forEach { it.onViewRemoved(this, child) }
}
-
- protected open fun getViewRect(view: IView): RectF {
- val v = view.view
- val rect = RectF()
- rect.left = v.left.toFloat()
- rect.top = v.top.toFloat()
- rect.right = rect.left + v.width
- rect.bottom = rect.top + v.height
- return rect
- }
-
- private fun topHalf(src: RectF): RectF {
- val result = RectF(src)
- result.bottom -= result.height() / 2
- return src
- }
-
- private fun bottomHalf(src: RectF): RectF {
- val result = RectF(src)
- result.top += result.height() / 2
- return src
- }
}
diff --git a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewImpl.kt b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewImpl.kt
index 71a4963f8..d4ea4bbf2 100644
--- a/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewImpl.kt
+++ b/xml-inflater/src/main/java/com/itsaky/androidide/inflater/internal/ViewImpl.kt
@@ -42,8 +42,6 @@ constructor(
private var fg: Drawable? = null
private var touched: Drawable? = null
-
- var includeInIndexComputation = true
internal val attributes = mutableListOf()