mirror of
https://github.com/jrpie/Launcher.git
synced 2025-05-11 13:04:17 +02:00
fix problem with multiple WidgetOverlayViews
This commit is contained in:
parent
24e90deb62
commit
061f3a1e77
3 changed files with 58 additions and 44 deletions
|
@ -41,7 +41,7 @@ open class WidgetContainerView(
|
|||
widgets.filter { it.panelId == widgetPanelId }.forEach { widget ->
|
||||
widget.createView(activity)?.let {
|
||||
addView(it, LayoutParams(widget.position))
|
||||
widgetViewById.put(widget.id, it)
|
||||
widgetViewById[widget.id] = it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,8 @@ const val EXTRA_PANEL_ID = "widgetPanelId"
|
|||
// We can't use AppCompatActivity, since some AppWidgets don't work there.
|
||||
class ManageWidgetsActivity : Activity(), UIObject {
|
||||
|
||||
var panelId: Int = WidgetPanel.HOME.id
|
||||
private var panelId: Int = WidgetPanel.HOME.id
|
||||
|
||||
|
||||
// We can't observe the livedata because this is not an AppCompatActivity
|
||||
private var sharedPreferencesListener =
|
||||
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
||||
if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
||||
|
|
|
@ -17,15 +17,12 @@ import android.view.ViewConfiguration
|
|||
import androidx.core.graphics.contains
|
||||
import androidx.core.graphics.minus
|
||||
import androidx.core.graphics.toRect
|
||||
import androidx.core.view.children
|
||||
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
||||
import de.jrpie.android.launcher.widgets.GRID_SIZE
|
||||
import de.jrpie.android.launcher.widgets.Widget
|
||||
import de.jrpie.android.launcher.widgets.WidgetPanel
|
||||
import de.jrpie.android.launcher.widgets.WidgetPosition
|
||||
import de.jrpie.android.launcher.widgets.updateWidget
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* A variant of the [WidgetContainerView] which allows to manage widgets.
|
||||
|
@ -38,6 +35,9 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
|||
val TOUCH_SLOP_SQUARE: Int
|
||||
val LONG_PRESS_TIMEOUT: Long
|
||||
|
||||
|
||||
private var overlayViewById = HashMap<Int, WidgetOverlayView>()
|
||||
|
||||
init {
|
||||
val configuration = ViewConfiguration.get(context)
|
||||
TOUCH_SLOP = configuration.scaledTouchSlop
|
||||
|
@ -47,36 +47,37 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
|||
}
|
||||
|
||||
|
||||
|
||||
enum class EditMode(val resize: (dx: Int, dy: Int, screenWidth: Int, screenHeight: Int, rect: Rect) -> Rect) {
|
||||
MOVE({ dx, dy, sw, sh, rect ->
|
||||
val cdx = dx.coerceIn(-rect.left, sw - rect.right)
|
||||
val cdy = dy.coerceIn(-rect.top, sh - rect.bottom)
|
||||
Rect(rect.left + cdx, rect.top + cdy, rect.right + cdx, rect.bottom + cdy)
|
||||
}),
|
||||
TOP({ dx, dy, sw, sh, rect ->
|
||||
TOP({ _, dy, _, sh, rect ->
|
||||
val cdy = dy.coerceIn(-rect.top, rect.bottom - rect.top - (2 * sh / GRID_SIZE) + 5)
|
||||
Rect(rect.left, rect.top + cdy, rect.right, rect.bottom)
|
||||
}),
|
||||
BOTTOM({ dx, dy, sw, sh, rect ->
|
||||
val cdy = dy.coerceIn((2 * sh / GRID_SIZE) + 5 + rect.top - rect.bottom, sh - rect.bottom)
|
||||
BOTTOM({ _, dy, _, sh, rect ->
|
||||
val cdy =
|
||||
dy.coerceIn((2 * sh / GRID_SIZE) + 5 + rect.top - rect.bottom, sh - rect.bottom)
|
||||
Rect(rect.left, rect.top, rect.right, rect.bottom + cdy)
|
||||
}),
|
||||
LEFT({ dx, dy, sw, sh, rect ->
|
||||
LEFT({ dx, _, sw, _, rect ->
|
||||
val cdx = dx.coerceIn(-rect.left, rect.right - rect.left - (2 * sw / GRID_SIZE) + 5)
|
||||
Rect(rect.left + cdx, rect.top, rect.right, rect.bottom)
|
||||
}),
|
||||
RIGHT({ dx, dy, sw, sh, rect ->
|
||||
val cdx = dx.coerceIn((2 * sw / GRID_SIZE) + 5 + rect.left - rect.right, sw - rect.right)
|
||||
RIGHT({ dx, _, sw, _, rect ->
|
||||
val cdx =
|
||||
dx.coerceIn((2 * sw / GRID_SIZE) + 5 + rect.left - rect.right, sw - rect.right)
|
||||
Rect(rect.left, rect.top, rect.right + cdx, rect.bottom)
|
||||
}),
|
||||
}
|
||||
|
||||
var selectedWidgetOverlayView: WidgetOverlayView? = null
|
||||
var selectedWidgetView: View? = null
|
||||
var currentGestureStart: Point? = null
|
||||
var startWidgetPosition: Rect? = null
|
||||
var lastPosition = Rect()
|
||||
private var selectedWidgetOverlayView: WidgetOverlayView? = null
|
||||
private var selectedWidgetView: View? = null
|
||||
private var currentGestureStart: Point? = null
|
||||
private var startWidgetPosition: Rect? = null
|
||||
private var lastPosition = Rect()
|
||||
|
||||
private val longPressHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
|
@ -94,17 +95,31 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
|||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||
val start = Point(event.x.toInt(), event.y.toInt())
|
||||
currentGestureStart = start
|
||||
val view = children.mapNotNull { it as? WidgetOverlayView }.firstOrNull {
|
||||
RectF(it.x, it.y, it.x + it.width, it.y + it.height).toRect().contains(start) == true
|
||||
} ?: return false
|
||||
val view = overlayViewById.asIterable()
|
||||
.map { it.value }.firstOrNull { overlayView ->
|
||||
RectF(
|
||||
overlayView.x,
|
||||
overlayView.y,
|
||||
overlayView.x + overlayView.width,
|
||||
overlayView.y + overlayView.height
|
||||
)
|
||||
.toRect()
|
||||
.contains(start)
|
||||
} ?: return true
|
||||
|
||||
val position = (view.layoutParams as Companion.LayoutParams).position.getAbsoluteRect(width, height)
|
||||
val position =
|
||||
(view.layoutParams as Companion.LayoutParams).position.getAbsoluteRect(
|
||||
width,
|
||||
height
|
||||
)
|
||||
selectedWidgetOverlayView = view
|
||||
selectedWidgetView = widgetViewById.get(view.widgetId) ?: return true
|
||||
selectedWidgetView = widgetViewById[view.widgetId] ?: return true
|
||||
startWidgetPosition = position
|
||||
|
||||
val positionInView = start.minus(Point(position.left, position.top))
|
||||
view.mode = view.getHandles().firstOrNull { it.position.contains(positionInView) }?.mode ?: EditMode.MOVE
|
||||
view.mode =
|
||||
view.getHandles().firstOrNull { it.position.contains(positionInView) }?.mode
|
||||
?: EditMode.MOVE
|
||||
|
||||
longPressHandler.postDelayed({
|
||||
synchronized(this@WidgetManagerView) {
|
||||
|
@ -124,19 +139,20 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
|||
}
|
||||
val view = selectedWidgetOverlayView ?: return true
|
||||
val start = startWidgetPosition ?: return true
|
||||
val absoluteNewPosition = view.mode?.resize(
|
||||
val absoluteNewPosition = (view.mode ?: return true).resize(
|
||||
distanceX.toInt(),
|
||||
distanceY.toInt(),
|
||||
width, height,
|
||||
start
|
||||
) ?: return true
|
||||
)
|
||||
val newPosition = WidgetPosition.fromAbsoluteRect(
|
||||
absoluteNewPosition, width, height
|
||||
)
|
||||
if (newPosition != lastPosition) {
|
||||
if (absoluteNewPosition != lastPosition) {
|
||||
lastPosition = absoluteNewPosition
|
||||
(view.layoutParams as Companion.LayoutParams).position = newPosition
|
||||
(selectedWidgetView?.layoutParams as? Companion.LayoutParams)?.position = newPosition
|
||||
(selectedWidgetView?.layoutParams as? Companion.LayoutParams)?.position =
|
||||
newPosition
|
||||
requestLayout()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_PRESS)
|
||||
|
@ -156,10 +172,9 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun endInteraction() {
|
||||
startWidgetPosition = null
|
||||
selectedWidgetOverlayView?.mode = null
|
||||
|
@ -167,16 +182,17 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
|||
|
||||
override fun updateWidgets(activity: Activity, widgets: Collection<Widget>?) {
|
||||
super.updateWidgets(activity, widgets)
|
||||
if (widgets == null) {
|
||||
return
|
||||
}
|
||||
children.filter { it is WidgetOverlayView }.forEach { removeView(it) }
|
||||
|
||||
widgets.filter { it.panelId == widgetPanelId }.forEach { widget ->
|
||||
synchronized(overlayViewById) {
|
||||
overlayViewById.forEach { removeView(it.value) }
|
||||
overlayViewById.clear()
|
||||
widgets?.filter { it.panelId == widgetPanelId }?.forEach { widget ->
|
||||
WidgetOverlayView(activity).let {
|
||||
addView(it)
|
||||
it.widgetId = widget.id
|
||||
addView(it)
|
||||
(it.layoutParams as Companion.LayoutParams).position = widget.position
|
||||
overlayViewById[widget.id] = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue