handle storing and redrawing widgets

This commit is contained in:
tibbi 2022-09-27 13:02:19 +02:00
parent e83aef8d9d
commit 5fca4ff4f1
1 changed files with 76 additions and 47 deletions

View File

@ -34,6 +34,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
private var textPaint: TextPaint private var textPaint: TextPaint
private var dragShadowCirclePaint: Paint private var dragShadowCirclePaint: Paint
private var draggedItem: HomeScreenGridItem? = null private var draggedItem: HomeScreenGridItem? = null
private var isFirstDraw = true
// let's use a 6x5 grid for now with 1 special row at the bottom, prefilled with default apps // let's use a 6x5 grid for now with 1 special row at the bottom, prefilled with default apps
private var rowXCoords = ArrayList<Int>(COLUMN_COUNT) private var rowXCoords = ArrayList<Int>(COLUMN_COUNT)
@ -236,25 +237,17 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
if (areAllCellsEmpty) { if (areAllCellsEmpty) {
val infoList = AppWidgetManager.getInstance(context).installedProviders val widgetItem = draggedItem!!.copy()
val appWidgetProviderInfo = infoList.firstOrNull { it.provider.shortClassName == draggedItem?.shortClassName } widgetItem.apply {
if (appWidgetProviderInfo != null) { left = widgetRect.left
val appWidgetHost = AppWidgetHost(context, WIDGET_HOST_ID) top = widgetRect.top
val appWidgetId = appWidgetHost.allocateAppWidgetId() right = widgetRect.right
val appWidgetManager = AppWidgetManager.getInstance(context) bottom = widgetRect.bottom
val canCreateWidget = appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, appWidgetProviderInfo.provider) }
if (canCreateWidget) {
if (appWidgetProviderInfo.configure != null) { bindWidget(widgetItem, false)
appWidgetHost.startAppWidgetConfigureActivityForResult(context as MainActivity, appWidgetId, 0, REQUEST_CONFIGURE_WIDGET, null) ensureBackgroundThread {
} else { context.homeScreenGridItemsDB.insert(widgetItem)
val widgetView = appWidgetHost.createView(context, appWidgetId, appWidgetProviderInfo)
widgetView.x = widgetRect.left * rowWidth + sideMargins.left.toFloat()
widgetView.y = widgetRect.top * rowHeight + sideMargins.top.toFloat()
val widgetWidth = draggedItem!!.widthCells * rowWidth
val widgetHeight = draggedItem!!.heightCells * rowHeight
addView(widgetView, widgetWidth, widgetHeight)
}
}
} }
} else { } else {
performHapticFeedback() performHapticFeedback()
@ -266,6 +259,29 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
redrawGrid() redrawGrid()
} }
private fun bindWidget(item: HomeScreenGridItem, isInitialDrawAfterLaunch: Boolean) {
val infoList = AppWidgetManager.getInstance(context).installedProviders
val appWidgetProviderInfo = infoList.firstOrNull { it.provider.shortClassName == item.shortClassName }
if (appWidgetProviderInfo != null) {
val appWidgetHost = AppWidgetHost(context, WIDGET_HOST_ID)
val appWidgetId = appWidgetHost.allocateAppWidgetId()
val appWidgetManager = AppWidgetManager.getInstance(context)
val canCreateWidget = appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, appWidgetProviderInfo.provider)
if (canCreateWidget) {
if (appWidgetProviderInfo.configure != null && !isInitialDrawAfterLaunch) {
appWidgetHost.startAppWidgetConfigureActivityForResult(context as MainActivity, appWidgetId, 0, REQUEST_CONFIGURE_WIDGET, null)
} else {
val widgetView = appWidgetHost.createView(context, appWidgetId, appWidgetProviderInfo)
widgetView.x = item.left * rowWidth + sideMargins.left.toFloat()
widgetView.y = item.top * rowHeight + sideMargins.top.toFloat()
val widgetWidth = item.widthCells * rowWidth
val widgetHeight = item.heightCells * rowHeight
addView(widgetView, widgetWidth, widgetHeight)
}
}
}
}
// convert stuff like 102x192 to grid cells like 0x1 // convert stuff like 102x192 to grid cells like 0x1
private fun getClosestGridCells(center: Pair<Int, Int>): Pair<Int, Int>? { private fun getClosestGridCells(center: Pair<Int, Int>): Pair<Int, Int>? {
rowXCoords.forEachIndexed { xIndex, xCell -> rowXCoords.forEachIndexed { xIndex, xCell ->
@ -280,8 +296,10 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
private fun redrawGrid() { private fun redrawGrid() {
setWillNotDraw(false) post {
invalidate() setWillNotDraw(false)
invalidate()
}
} }
private fun getFakeWidth() = width - sideMargins.left - sideMargins.right private fun getFakeWidth() = width - sideMargins.left - sideMargins.right
@ -310,7 +328,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
} }
gridItems.filter { it.drawable != null }.forEach { item -> gridItems.filter { it.drawable != null && it.type == ITEM_TYPE_ICON }.forEach { item ->
if (item.id != draggedItem?.id) { if (item.id != draggedItem?.id) {
val drawableX = rowXCoords[item.left] + iconMargin + sideMargins.left val drawableX = rowXCoords[item.left] + iconMargin + sideMargins.left
@ -343,6 +361,12 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
} }
} }
if (isFirstDraw) {
gridItems.filter { it.type == ITEM_TYPE_WIDGET }.forEach { item ->
bindWidget(item, true)
}
}
if (draggedItem != null && draggedItemCurrentCoords.first != -1 && draggedItemCurrentCoords.second != -1) { if (draggedItem != null && draggedItemCurrentCoords.first != -1 && draggedItemCurrentCoords.second != -1) {
if (draggedItem!!.type == ITEM_TYPE_ICON || draggedItem!!.type == ITEM_TYPE_SHORTCUT) { if (draggedItem!!.type == ITEM_TYPE_ICON || draggedItem!!.type == ITEM_TYPE_SHORTCUT) {
// draw a circle under the current cell // draw a circle under the current cell
@ -368,35 +392,40 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Rel
draggedItem!!.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize) draggedItem!!.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
draggedItem!!.drawable!!.draw(canvas) draggedItem!!.drawable!!.draw(canvas)
} else if (draggedItem!!.type == ITEM_TYPE_WIDGET) { } else if (draggedItem!!.type == ITEM_TYPE_WIDGET) {
val center = gridCenters.minBy { // at first draw we are loading the widget from the database at some exact spot, not dragging it
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top) if (!isFirstDraw) {
} val center = gridCenters.minBy {
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
}
val gridCells = getClosestGridCells(center) val gridCells = getClosestGridCells(center)
if (gridCells != null) { if (gridCells != null) {
val widgetRect = getWidgetOccupiedRect(gridCells) val widgetRect = getWidgetOccupiedRect(gridCells)
val leftSide = widgetRect.left * rowWidth + sideMargins.left + iconMargin.toFloat() val leftSide = widgetRect.left * rowWidth + sideMargins.left + iconMargin.toFloat()
val topSide = widgetRect.top * rowHeight + sideMargins.top + iconMargin.toFloat() val topSide = widgetRect.top * rowHeight + sideMargins.top + iconMargin.toFloat()
val rightSide = leftSide + draggedItem!!.widthCells * rowWidth - sideMargins.right - iconMargin.toFloat() val rightSide = leftSide + draggedItem!!.widthCells * rowWidth - sideMargins.right - iconMargin.toFloat()
val bottomSide = topSide + draggedItem!!.heightCells * rowHeight - sideMargins.top val bottomSide = topSide + draggedItem!!.heightCells * rowHeight - sideMargins.top
canvas.drawRoundRect(leftSide, topSide, rightSide, bottomSide, roundedCornerRadius, roundedCornerRadius, dragShadowCirclePaint) canvas.drawRoundRect(leftSide, topSide, rightSide, bottomSide, roundedCornerRadius, roundedCornerRadius, dragShadowCirclePaint)
} }
// show the widget preview itself at dragging // show the widget preview itself at dragging
val drawable = draggedItem!!.drawable!! val drawable = draggedItem!!.drawable!!
val aspectRatio = drawable.minimumHeight / drawable.minimumWidth.toFloat() val aspectRatio = drawable.minimumHeight / drawable.minimumWidth.toFloat()
val drawableX = (draggedItemCurrentCoords.first - drawable.minimumWidth / 2f).toInt() val drawableX = (draggedItemCurrentCoords.first - drawable.minimumWidth / 2f).toInt()
val drawableY = (draggedItemCurrentCoords.second - drawable.minimumHeight / 3f).toInt() val drawableY = (draggedItemCurrentCoords.second - drawable.minimumHeight / 3f).toInt()
val drawableWidth = draggedItem!!.widthCells * rowWidth - iconMargin * (draggedItem!!.widthCells - 1) val drawableWidth = draggedItem!!.widthCells * rowWidth - iconMargin * (draggedItem!!.widthCells - 1)
drawable.setBounds( drawable.setBounds(
drawableX, drawableX,
drawableY, drawableY,
drawableX + drawableWidth, drawableX + drawableWidth,
(drawableY + drawableWidth * aspectRatio).toInt() (drawableY + drawableWidth * aspectRatio).toInt()
) )
drawable.draw(canvas) drawable.draw(canvas)
}
} }
} }
isFirstDraw = false
} }
// get the clickable area around the icon, it includes text too // get the clickable area around the icon, it includes text too