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 ->
|
widgets.filter { it.panelId == widgetPanelId }.forEach { widget ->
|
||||||
widget.createView(activity)?.let {
|
widget.createView(activity)?.let {
|
||||||
addView(it, LayoutParams(widget.position))
|
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.
|
// We can't use AppCompatActivity, since some AppWidgets don't work there.
|
||||||
class ManageWidgetsActivity : Activity(), UIObject {
|
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 =
|
private var sharedPreferencesListener =
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
||||||
if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
||||||
|
|
|
@ -17,15 +17,12 @@ import android.view.ViewConfiguration
|
||||||
import androidx.core.graphics.contains
|
import androidx.core.graphics.contains
|
||||||
import androidx.core.graphics.minus
|
import androidx.core.graphics.minus
|
||||||
import androidx.core.graphics.toRect
|
import androidx.core.graphics.toRect
|
||||||
import androidx.core.view.children
|
|
||||||
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
||||||
import de.jrpie.android.launcher.widgets.GRID_SIZE
|
import de.jrpie.android.launcher.widgets.GRID_SIZE
|
||||||
import de.jrpie.android.launcher.widgets.Widget
|
import de.jrpie.android.launcher.widgets.Widget
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPanel
|
import de.jrpie.android.launcher.widgets.WidgetPanel
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPosition
|
import de.jrpie.android.launcher.widgets.WidgetPosition
|
||||||
import de.jrpie.android.launcher.widgets.updateWidget
|
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.
|
* 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 TOUCH_SLOP_SQUARE: Int
|
||||||
val LONG_PRESS_TIMEOUT: Long
|
val LONG_PRESS_TIMEOUT: Long
|
||||||
|
|
||||||
|
|
||||||
|
private var overlayViewById = HashMap<Int, WidgetOverlayView>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val configuration = ViewConfiguration.get(context)
|
val configuration = ViewConfiguration.get(context)
|
||||||
TOUCH_SLOP = configuration.scaledTouchSlop
|
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) {
|
enum class EditMode(val resize: (dx: Int, dy: Int, screenWidth: Int, screenHeight: Int, rect: Rect) -> Rect) {
|
||||||
MOVE({ dx, dy, sw, sh, rect ->
|
MOVE({ dx, dy, sw, sh, rect ->
|
||||||
val cdx = dx.coerceIn(-rect.left, sw - rect.right)
|
val cdx = dx.coerceIn(-rect.left, sw - rect.right)
|
||||||
val cdy = dy.coerceIn(-rect.top, sh - rect.bottom)
|
val cdy = dy.coerceIn(-rect.top, sh - rect.bottom)
|
||||||
Rect(rect.left + cdx, rect.top + cdy, rect.right + cdx, rect.bottom + cdy)
|
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)
|
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)
|
Rect(rect.left, rect.top + cdy, rect.right, rect.bottom)
|
||||||
}),
|
}),
|
||||||
BOTTOM({ dx, dy, sw, sh, rect ->
|
BOTTOM({ _, dy, _, sh, rect ->
|
||||||
val cdy = dy.coerceIn((2 * sh / GRID_SIZE) + 5 + rect.top - rect.bottom, sh - rect.bottom)
|
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)
|
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)
|
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)
|
Rect(rect.left + cdx, rect.top, rect.right, rect.bottom)
|
||||||
}),
|
}),
|
||||||
RIGHT({ dx, dy, sw, sh, rect ->
|
RIGHT({ dx, _, sw, _, rect ->
|
||||||
val cdx = dx.coerceIn((2 * sw / GRID_SIZE) + 5 + rect.left - rect.right, sw - rect.right)
|
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)
|
Rect(rect.left, rect.top, rect.right + cdx, rect.bottom)
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedWidgetOverlayView: WidgetOverlayView? = null
|
private var selectedWidgetOverlayView: WidgetOverlayView? = null
|
||||||
var selectedWidgetView: View? = null
|
private var selectedWidgetView: View? = null
|
||||||
var currentGestureStart: Point? = null
|
private var currentGestureStart: Point? = null
|
||||||
var startWidgetPosition: Rect? = null
|
private var startWidgetPosition: Rect? = null
|
||||||
var lastPosition = Rect()
|
private var lastPosition = Rect()
|
||||||
|
|
||||||
private val longPressHandler = Handler(Looper.getMainLooper())
|
private val longPressHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
@ -94,17 +95,31 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||||
val start = Point(event.x.toInt(), event.y.toInt())
|
val start = Point(event.x.toInt(), event.y.toInt())
|
||||||
currentGestureStart = start
|
currentGestureStart = start
|
||||||
val view = children.mapNotNull { it as? WidgetOverlayView }.firstOrNull {
|
val view = overlayViewById.asIterable()
|
||||||
RectF(it.x, it.y, it.x + it.width, it.y + it.height).toRect().contains(start) == true
|
.map { it.value }.firstOrNull { overlayView ->
|
||||||
} ?: return false
|
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
|
selectedWidgetOverlayView = view
|
||||||
selectedWidgetView = widgetViewById.get(view.widgetId) ?: return true
|
selectedWidgetView = widgetViewById[view.widgetId] ?: return true
|
||||||
startWidgetPosition = position
|
startWidgetPosition = position
|
||||||
|
|
||||||
val positionInView = start.minus(Point(position.left, position.top))
|
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({
|
longPressHandler.postDelayed({
|
||||||
synchronized(this@WidgetManagerView) {
|
synchronized(this@WidgetManagerView) {
|
||||||
|
@ -124,19 +139,20 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
}
|
}
|
||||||
val view = selectedWidgetOverlayView ?: return true
|
val view = selectedWidgetOverlayView ?: return true
|
||||||
val start = startWidgetPosition ?: return true
|
val start = startWidgetPosition ?: return true
|
||||||
val absoluteNewPosition = view.mode?.resize(
|
val absoluteNewPosition = (view.mode ?: return true).resize(
|
||||||
distanceX.toInt(),
|
distanceX.toInt(),
|
||||||
distanceY.toInt(),
|
distanceY.toInt(),
|
||||||
width, height,
|
width, height,
|
||||||
start
|
start
|
||||||
) ?: return true
|
)
|
||||||
val newPosition = WidgetPosition.fromAbsoluteRect(
|
val newPosition = WidgetPosition.fromAbsoluteRect(
|
||||||
absoluteNewPosition, width, height
|
absoluteNewPosition, width, height
|
||||||
)
|
)
|
||||||
if (newPosition != lastPosition) {
|
if (absoluteNewPosition != lastPosition) {
|
||||||
lastPosition = absoluteNewPosition
|
lastPosition = absoluteNewPosition
|
||||||
(view.layoutParams as Companion.LayoutParams).position = newPosition
|
(view.layoutParams as Companion.LayoutParams).position = newPosition
|
||||||
(selectedWidgetView?.layoutParams as? Companion.LayoutParams)?.position = newPosition
|
(selectedWidgetView?.layoutParams as? Companion.LayoutParams)?.position =
|
||||||
|
newPosition
|
||||||
requestLayout()
|
requestLayout()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_PRESS)
|
view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_PRESS)
|
||||||
|
@ -156,10 +172,9 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun endInteraction() {
|
private fun endInteraction() {
|
||||||
startWidgetPosition = null
|
startWidgetPosition = null
|
||||||
selectedWidgetOverlayView?.mode = null
|
selectedWidgetOverlayView?.mode = null
|
||||||
|
@ -167,16 +182,17 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
|
|
||||||
override fun updateWidgets(activity: Activity, widgets: Collection<Widget>?) {
|
override fun updateWidgets(activity: Activity, widgets: Collection<Widget>?) {
|
||||||
super.updateWidgets(activity, widgets)
|
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) {
|
||||||
WidgetOverlayView(activity).let {
|
overlayViewById.forEach { removeView(it.value) }
|
||||||
addView(it)
|
overlayViewById.clear()
|
||||||
it.widgetId = widget.id
|
widgets?.filter { it.panelId == widgetPanelId }?.forEach { widget ->
|
||||||
(it.layoutParams as Companion.LayoutParams).position = widget.position
|
WidgetOverlayView(activity).let {
|
||||||
|
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