mirror of
https://github.com/SimpleMobileTools/Simple-Launcher.git
synced 2025-06-01 19:39:16 +02:00
553 lines
23 KiB
Kotlin
553 lines
23 KiB
Kotlin
package com.simplemobiletools.launcher.views
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.appwidget.AppWidgetManager
|
|
import android.appwidget.AppWidgetProviderInfo
|
|
import android.content.Context
|
|
import android.graphics.Canvas
|
|
import android.graphics.Color
|
|
import android.graphics.Paint
|
|
import android.graphics.Rect
|
|
import android.graphics.drawable.BitmapDrawable
|
|
import android.text.Layout
|
|
import android.text.StaticLayout
|
|
import android.text.TextPaint
|
|
import android.text.TextUtils
|
|
import android.util.AttributeSet
|
|
import android.widget.RelativeLayout
|
|
import com.simplemobiletools.commons.extensions.navigationBarHeight
|
|
import com.simplemobiletools.commons.extensions.performHapticFeedback
|
|
import com.simplemobiletools.commons.extensions.statusBarHeight
|
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
|
import com.simplemobiletools.launcher.R
|
|
import com.simplemobiletools.launcher.activities.MainActivity
|
|
import com.simplemobiletools.launcher.extensions.getDrawableForPackageName
|
|
import com.simplemobiletools.launcher.extensions.homeScreenGridItemsDB
|
|
import com.simplemobiletools.launcher.helpers.*
|
|
import com.simplemobiletools.launcher.models.HomeScreenGridItem
|
|
|
|
class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : RelativeLayout(context, attrs, defStyle) {
|
|
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
|
|
|
|
private var iconMargin = context.resources.getDimension(R.dimen.icon_side_margin).toInt()
|
|
private var labelSideMargin = context.resources.getDimension(R.dimen.small_margin).toInt()
|
|
private var roundedCornerRadius = context.resources.getDimension(R.dimen.activity_margin)
|
|
private var textPaint: TextPaint
|
|
private var dragShadowCirclePaint: Paint
|
|
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
|
|
private var rowXCoords = ArrayList<Int>(COLUMN_COUNT)
|
|
private var rowYCoords = ArrayList<Int>(ROW_COUNT)
|
|
private var rowWidth = 0
|
|
private var rowHeight = 0
|
|
private var iconSize = 0
|
|
|
|
// apply fake margins at the home screen. Real ones would cause the icons be cut at dragging at screen sides
|
|
private var sideMargins = Rect()
|
|
|
|
private var gridItems = ArrayList<HomeScreenGridItem>()
|
|
private var gridCenters = ArrayList<Pair<Int, Int>>()
|
|
private var draggedItemCurrentCoords = Pair(-1, -1)
|
|
private var widgetViews = ArrayList<MyAppWidgetHostView>()
|
|
|
|
val appWidgetHost = MyAppWidgetHost(context, WIDGET_HOST_ID)
|
|
private val appWidgetManager = AppWidgetManager.getInstance(context)
|
|
|
|
init {
|
|
textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
color = Color.WHITE
|
|
textSize = context.resources.getDimension(R.dimen.smaller_text_size)
|
|
setShadowLayer(.5f, 0f, 0f, Color.BLACK)
|
|
}
|
|
|
|
dragShadowCirclePaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
color = context.resources.getColor(R.color.light_grey_stroke)
|
|
strokeWidth = context.resources.getDimension(R.dimen.small_margin)
|
|
style = Paint.Style.STROKE
|
|
}
|
|
|
|
val sideMargin = context.resources.getDimension(R.dimen.normal_margin).toInt()
|
|
sideMargins.apply {
|
|
top = context.statusBarHeight
|
|
bottom = context.navigationBarHeight
|
|
left = sideMargin
|
|
right = sideMargin
|
|
}
|
|
|
|
fetchGridItems()
|
|
}
|
|
|
|
fun fetchGridItems() {
|
|
ensureBackgroundThread {
|
|
gridItems = context.homeScreenGridItemsDB.getAllItems() as ArrayList<HomeScreenGridItem>
|
|
gridItems.forEach { item ->
|
|
if (item.type == ITEM_TYPE_ICON) {
|
|
item.drawable = context.getDrawableForPackageName(item.packageName)
|
|
}
|
|
}
|
|
|
|
redrawGrid()
|
|
}
|
|
}
|
|
|
|
fun removeAppIcon(item: HomeScreenGridItem) {
|
|
ensureBackgroundThread {
|
|
removeItemFromHomeScreen(item)
|
|
post {
|
|
removeView(widgetViews.firstOrNull { it.tag == item.widgetId })
|
|
}
|
|
|
|
gridItems.removeIf { it.id == item.id }
|
|
redrawGrid()
|
|
}
|
|
}
|
|
|
|
private fun removeItemFromHomeScreen(item: HomeScreenGridItem) {
|
|
ensureBackgroundThread {
|
|
if (item.id != null) {
|
|
context.homeScreenGridItemsDB.deleteById(item.id!!)
|
|
}
|
|
|
|
if (item.type == ITEM_TYPE_WIDGET) {
|
|
appWidgetHost.deleteAppWidgetId(item.widgetId)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun itemDraggingStarted(draggedGridItem: HomeScreenGridItem) {
|
|
draggedItem = draggedGridItem
|
|
if (draggedItem!!.drawable == null) {
|
|
draggedItem!!.drawable = context.getDrawableForPackageName(draggedGridItem.packageName)
|
|
}
|
|
|
|
redrawGrid()
|
|
}
|
|
|
|
fun draggedItemMoved(x: Int, y: Int) {
|
|
if (draggedItem == null) {
|
|
return
|
|
}
|
|
|
|
draggedItemCurrentCoords = Pair(x, y)
|
|
redrawGrid()
|
|
}
|
|
|
|
// figure out at which cell was the item dropped, if it is empty
|
|
fun itemDraggingStopped() {
|
|
if (draggedItem == null) {
|
|
return
|
|
}
|
|
|
|
when (draggedItem!!.type) {
|
|
ITEM_TYPE_ICON -> addAppIcon()
|
|
ITEM_TYPE_WIDGET -> addWidget()
|
|
ITEM_TYPE_SHORTCUT -> {
|
|
// replace this with real shortcut handling
|
|
draggedItem = null
|
|
redrawGrid()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun addAppIcon() {
|
|
val center = gridCenters.minBy {
|
|
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
|
}
|
|
|
|
var redrawIcons = false
|
|
val gridCells = getClosestGridCells(center)
|
|
if (gridCells != null) {
|
|
val xIndex = gridCells.first
|
|
val yIndex = gridCells.second
|
|
|
|
// check if the destination cell is empty
|
|
var areAllCellsEmpty = true
|
|
val wantedCell = Pair(xIndex, yIndex)
|
|
gridItems.forEach { item ->
|
|
for (xCell in item.left until item.right) {
|
|
for (yCell in item.top until item.bottom) {
|
|
val cell = Pair(xCell, yCell)
|
|
val isAnyCellOccupied = wantedCell == cell
|
|
if (isAnyCellOccupied) {
|
|
areAllCellsEmpty = false
|
|
return@forEach
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (areAllCellsEmpty) {
|
|
val draggedHomeGridItem = gridItems.firstOrNull { it.id == draggedItem?.id }
|
|
|
|
// we are moving an existing home screen item from one place to another
|
|
if (draggedHomeGridItem != null) {
|
|
draggedHomeGridItem.apply {
|
|
left = xIndex
|
|
top = yIndex
|
|
right = xIndex + 1
|
|
bottom = yIndex + 1
|
|
|
|
ensureBackgroundThread {
|
|
context.homeScreenGridItemsDB.updateItemPosition(left, top, right, bottom, id!!)
|
|
}
|
|
}
|
|
redrawIcons = true
|
|
} else if (draggedItem != null) {
|
|
// we are dragging a new item at the home screen from the All Apps fragment
|
|
val newHomeScreenGridItem = HomeScreenGridItem(
|
|
null,
|
|
xIndex,
|
|
yIndex,
|
|
xIndex + 1,
|
|
yIndex + 1,
|
|
1,
|
|
1,
|
|
draggedItem!!.packageName,
|
|
draggedItem!!.title,
|
|
draggedItem!!.type,
|
|
"",
|
|
-1,
|
|
draggedItem!!.drawable
|
|
)
|
|
|
|
ensureBackgroundThread {
|
|
val newId = context.homeScreenGridItemsDB.insert(newHomeScreenGridItem)
|
|
newHomeScreenGridItem.id = newId
|
|
gridItems.add(newHomeScreenGridItem)
|
|
redrawGrid()
|
|
}
|
|
}
|
|
} else {
|
|
performHapticFeedback()
|
|
redrawIcons = true
|
|
}
|
|
}
|
|
|
|
draggedItem = null
|
|
draggedItemCurrentCoords = Pair(-1, -1)
|
|
if (redrawIcons) {
|
|
redrawGrid()
|
|
}
|
|
}
|
|
|
|
private fun addWidget() {
|
|
val center = gridCenters.minBy {
|
|
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
|
}
|
|
|
|
val gridCells = getClosestGridCells(center)
|
|
if (gridCells != null) {
|
|
val widgetRect = getWidgetOccupiedRect(gridCells)
|
|
val widgetTargetCells = ArrayList<Pair<Int, Int>>()
|
|
for (xCell in widgetRect.left until widgetRect.right) {
|
|
for (yCell in widgetRect.top until widgetRect.bottom) {
|
|
widgetTargetCells.add(Pair(xCell, yCell))
|
|
}
|
|
}
|
|
|
|
var areAllCellsEmpty = true
|
|
gridItems.filter { it.id != draggedItem?.id }.forEach { item ->
|
|
for (xCell in item.left until item.right) {
|
|
for (yCell in item.top until item.bottom) {
|
|
val cell = Pair(xCell, yCell)
|
|
val isAnyCellOccupied = widgetTargetCells.contains(cell)
|
|
if (isAnyCellOccupied) {
|
|
areAllCellsEmpty = false
|
|
return@forEach
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (areAllCellsEmpty) {
|
|
val widgetItem = draggedItem!!.copy()
|
|
widgetItem.apply {
|
|
left = widgetRect.left
|
|
top = widgetRect.top
|
|
right = widgetRect.right
|
|
bottom = widgetRect.bottom
|
|
}
|
|
|
|
ensureBackgroundThread {
|
|
// store the new widget at creating it, else just move the existing one
|
|
if (widgetItem.id == null) {
|
|
val itemId = context.homeScreenGridItemsDB.insert(widgetItem)
|
|
widgetItem.id = itemId
|
|
post {
|
|
bindWidget(widgetItem, false)
|
|
}
|
|
} else {
|
|
context.homeScreenGridItemsDB.updateItemPosition(widgetItem.left, widgetItem.top, widgetItem.right, widgetItem.bottom, widgetItem.id!!)
|
|
val widgetView = widgetViews.firstOrNull { it.tag == widgetItem.widgetId }
|
|
if (widgetView != null) {
|
|
widgetView.x = calculateWidgetX(widgetItem.left)
|
|
widgetView.y = calculateWidgetY(widgetItem.top)
|
|
}
|
|
|
|
gridItems.firstOrNull { it.id == widgetItem.id }?.apply {
|
|
left = widgetItem.left
|
|
right = widgetItem.right
|
|
top = widgetItem.top
|
|
bottom = widgetItem.bottom
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
performHapticFeedback()
|
|
}
|
|
}
|
|
|
|
draggedItem = null
|
|
draggedItemCurrentCoords = Pair(-1, -1)
|
|
redrawGrid()
|
|
}
|
|
|
|
private fun bindWidget(item: HomeScreenGridItem, isInitialDrawAfterLaunch: Boolean) {
|
|
val activity = context as MainActivity
|
|
val infoList = appWidgetManager!!.installedProviders
|
|
val appWidgetProviderInfo = infoList.firstOrNull { it.provider.className == item.className }
|
|
if (appWidgetProviderInfo != null) {
|
|
val appWidgetId = appWidgetHost.allocateAppWidgetId()
|
|
activity.handleWidgetBinding(appWidgetManager, appWidgetId, appWidgetProviderInfo) { canBind ->
|
|
if (canBind) {
|
|
if (appWidgetProviderInfo.configure != null && !isInitialDrawAfterLaunch) {
|
|
activity.handleWidgetConfigureScreen(appWidgetHost, appWidgetId) { success ->
|
|
if (success) {
|
|
placeAppWidget(appWidgetId, appWidgetProviderInfo, item)
|
|
} else {
|
|
removeItemFromHomeScreen(item)
|
|
}
|
|
}
|
|
} else {
|
|
placeAppWidget(appWidgetId, appWidgetProviderInfo, item)
|
|
}
|
|
} else {
|
|
removeItemFromHomeScreen(item)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun placeAppWidget(appWidgetId: Int, appWidgetProviderInfo: AppWidgetProviderInfo, item: HomeScreenGridItem) {
|
|
item.widgetId = appWidgetId
|
|
// we have to pass the base context here, else there will be errors with the themes
|
|
val widgetView = appWidgetHost.createView((context as MainActivity).baseContext, appWidgetId, appWidgetProviderInfo) as MyAppWidgetHostView
|
|
widgetView.tag = appWidgetId
|
|
widgetView.setAppWidget(appWidgetId, appWidgetProviderInfo)
|
|
widgetView.longPressListener = { x, y ->
|
|
val yOffset = resources.getDimension(R.dimen.home_long_press_anchor_offset_y)
|
|
(context as? MainActivity)?.showHomeIconMenu(x, widgetView.y - yOffset, item, false)
|
|
|
|
val gridItem = gridItems.firstOrNull { it.widgetId == appWidgetId }
|
|
if (gridItem != null) {
|
|
widgetView.buildDrawingCache()
|
|
gridItem.drawable = BitmapDrawable(widgetView.drawingCache)
|
|
}
|
|
}
|
|
|
|
widgetView.x = calculateWidgetX(item.left)
|
|
widgetView.y = calculateWidgetY(item.top)
|
|
val widgetWidth = item.widthCells * rowWidth
|
|
val widgetHeight = item.heightCells * rowHeight
|
|
addView(widgetView, widgetWidth, widgetHeight)
|
|
widgetViews.add(widgetView)
|
|
|
|
// remove the drawable so that it gets refreshed on long press
|
|
item.drawable = null
|
|
gridItems.add(item)
|
|
}
|
|
|
|
private fun calculateWidgetX(leftCell: Int) = leftCell * rowWidth + sideMargins.left.toFloat()
|
|
|
|
private fun calculateWidgetY(topCell: Int) = topCell * rowHeight + sideMargins.top.toFloat()
|
|
|
|
// convert stuff like 102x192 to grid cells like 0x1
|
|
private fun getClosestGridCells(center: Pair<Int, Int>): Pair<Int, Int>? {
|
|
rowXCoords.forEachIndexed { xIndex, xCell ->
|
|
rowYCoords.forEachIndexed { yIndex, yCell ->
|
|
if (xCell + rowWidth / 2 == center.first && yCell + rowHeight / 2 == center.second) {
|
|
return Pair(xIndex, yIndex)
|
|
}
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
private fun redrawGrid() {
|
|
post {
|
|
setWillNotDraw(false)
|
|
invalidate()
|
|
}
|
|
}
|
|
|
|
private fun getFakeWidth() = width - sideMargins.left - sideMargins.right
|
|
|
|
private fun getFakeHeight() = height - sideMargins.top - sideMargins.bottom
|
|
|
|
@SuppressLint("DrawAllocation")
|
|
override fun onDraw(canvas: Canvas) {
|
|
super.onDraw(canvas)
|
|
if (rowXCoords.isEmpty()) {
|
|
rowWidth = getFakeWidth() / COLUMN_COUNT
|
|
rowHeight = getFakeHeight() / ROW_COUNT
|
|
iconSize = rowWidth - 2 * iconMargin
|
|
for (i in 0 until COLUMN_COUNT) {
|
|
rowXCoords.add(i, i * rowWidth)
|
|
}
|
|
|
|
for (i in 0 until ROW_COUNT) {
|
|
rowYCoords.add(i, i * rowHeight)
|
|
}
|
|
|
|
rowXCoords.forEach { x ->
|
|
rowYCoords.forEach { y ->
|
|
gridCenters.add(Pair(x + rowWidth / 2, y + rowHeight / 2))
|
|
}
|
|
}
|
|
}
|
|
|
|
gridItems.filter { it.drawable != null && it.type == ITEM_TYPE_ICON }.forEach { item ->
|
|
if (item.id != draggedItem?.id) {
|
|
val drawableX = rowXCoords[item.left] + iconMargin + sideMargins.left
|
|
|
|
// icons at the bottom are drawn at the bottom of the grid and they have no label
|
|
if (item.top == ROW_COUNT - 1) {
|
|
val drawableY = rowYCoords[item.top] + rowHeight - iconSize - iconMargin * 2 + sideMargins.top
|
|
item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
|
|
} else {
|
|
val drawableY = rowYCoords[item.top] + iconSize / 2 + sideMargins.top
|
|
item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
|
|
|
|
if (item.id != draggedItem?.id && item.title.isNotEmpty()) {
|
|
val textX = rowXCoords[item.left].toFloat() + labelSideMargin + sideMargins.left
|
|
val textY = rowYCoords[item.top] + iconSize * 1.5f + labelSideMargin + sideMargins.top
|
|
val staticLayout = StaticLayout.Builder
|
|
.obtain(item.title, 0, item.title.length, textPaint, rowWidth - 2 * labelSideMargin)
|
|
.setMaxLines(2)
|
|
.setEllipsize(TextUtils.TruncateAt.END)
|
|
.setAlignment(Layout.Alignment.ALIGN_CENTER)
|
|
.build()
|
|
|
|
canvas.save()
|
|
canvas.translate(textX, textY)
|
|
staticLayout.draw(canvas)
|
|
canvas.restore()
|
|
}
|
|
}
|
|
|
|
item.drawable!!.draw(canvas)
|
|
}
|
|
}
|
|
|
|
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!!.type == ITEM_TYPE_ICON || draggedItem!!.type == ITEM_TYPE_SHORTCUT) {
|
|
// draw a circle under the current cell
|
|
val center = gridCenters.minBy {
|
|
Math.abs(it.first - draggedItemCurrentCoords.first + sideMargins.left) + Math.abs(it.second - draggedItemCurrentCoords.second + sideMargins.top)
|
|
}
|
|
|
|
val gridCells = getClosestGridCells(center)
|
|
if (gridCells != null) {
|
|
val shadowX = rowXCoords[gridCells.first] + iconMargin.toFloat() + iconSize / 2 + sideMargins.left
|
|
val shadowY = if (gridCells.second == ROW_COUNT - 1) {
|
|
rowYCoords[gridCells.second] + rowHeight - iconSize / 2 - iconMargin * 2
|
|
} else {
|
|
rowYCoords[gridCells.second] + iconSize
|
|
} + sideMargins.top
|
|
|
|
canvas.drawCircle(shadowX, shadowY.toFloat(), iconSize / 2f, dragShadowCirclePaint)
|
|
}
|
|
|
|
// show the app icon itself at dragging, move it above the finger a bit to make it visible
|
|
val drawableX = (draggedItemCurrentCoords.first - iconSize / 1.5f).toInt()
|
|
val drawableY = (draggedItemCurrentCoords.second - iconSize / 1.2f).toInt()
|
|
draggedItem!!.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
|
|
draggedItem!!.drawable!!.draw(canvas)
|
|
} else if (draggedItem!!.type == ITEM_TYPE_WIDGET) {
|
|
// at first draw we are loading the widget from the database at some exact spot, not dragging it
|
|
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)
|
|
if (gridCells != null) {
|
|
val widgetRect = getWidgetOccupiedRect(gridCells)
|
|
val leftSide = widgetRect.left * rowWidth + sideMargins.left + iconMargin.toFloat()
|
|
val topSide = widgetRect.top * rowHeight + sideMargins.top + iconMargin.toFloat()
|
|
val rightSide = leftSide + draggedItem!!.widthCells * rowWidth - sideMargins.right - iconMargin.toFloat()
|
|
val bottomSide = topSide + draggedItem!!.heightCells * rowHeight - sideMargins.top
|
|
canvas.drawRoundRect(leftSide, topSide, rightSide, bottomSide, roundedCornerRadius, roundedCornerRadius, dragShadowCirclePaint)
|
|
}
|
|
|
|
// show the widget preview itself at dragging
|
|
val drawable = draggedItem!!.drawable!!
|
|
val aspectRatio = drawable.minimumHeight / drawable.minimumWidth.toFloat()
|
|
val drawableX = (draggedItemCurrentCoords.first - drawable.minimumWidth / 2f).toInt()
|
|
val drawableY = (draggedItemCurrentCoords.second - drawable.minimumHeight / 3f).toInt()
|
|
val drawableWidth = draggedItem!!.widthCells * rowWidth - iconMargin * (draggedItem!!.widthCells - 1)
|
|
drawable.setBounds(
|
|
drawableX,
|
|
drawableY,
|
|
drawableX + drawableWidth,
|
|
(drawableY + drawableWidth * aspectRatio).toInt()
|
|
)
|
|
drawable.draw(canvas)
|
|
}
|
|
}
|
|
}
|
|
|
|
isFirstDraw = false
|
|
}
|
|
|
|
// get the clickable area around the icon, it includes text too
|
|
private fun getClickableRect(item: HomeScreenGridItem): Rect {
|
|
val clickableLeft = item.left * rowWidth + sideMargins.left
|
|
val clickableTop = rowYCoords[item.top] + iconSize / 3 + sideMargins.top
|
|
return Rect(clickableLeft, clickableTop, clickableLeft + rowWidth, clickableTop + iconSize * 2)
|
|
}
|
|
|
|
// drag the center of the widget, not the top left corner
|
|
private fun getWidgetOccupiedRect(item: Pair<Int, Int>): Rect {
|
|
val left = item.first - Math.floor((draggedItem!!.widthCells - 1) / 2.0).toInt()
|
|
val rect = Rect(left, item.second, left + draggedItem!!.widthCells, item.second + draggedItem!!.heightCells)
|
|
if (rect.left < 0) {
|
|
rect.right -= rect.left
|
|
rect.left = 0
|
|
} else if (rect.right > COLUMN_COUNT) {
|
|
val diff = rect.right - COLUMN_COUNT
|
|
rect.right -= diff
|
|
rect.left -= diff
|
|
}
|
|
|
|
// do not allow placing widgets at the bottom row, that is for pinned default apps
|
|
if (rect.bottom >= ROW_COUNT) {
|
|
val diff = rect.bottom - ROW_COUNT + 1
|
|
rect.bottom -= diff
|
|
rect.top -= diff
|
|
}
|
|
|
|
return rect
|
|
}
|
|
|
|
fun isClickingGridItem(x: Int, y: Int): HomeScreenGridItem? {
|
|
for (gridItem in gridItems) {
|
|
val rect = getClickableRect(gridItem)
|
|
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
|
return gridItem
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
}
|