adding some Drag & Drop related improvements

This commit is contained in:
tibbi 2022-09-25 11:13:02 +02:00
parent d1a38d8a02
commit 92fd30eec2
3 changed files with 48 additions and 33 deletions

View File

@ -15,11 +15,8 @@ import android.telecom.TelecomManager
import android.view.* import android.view.*
import android.view.animation.DecelerateInterpolator import android.view.animation.DecelerateInterpolator
import android.widget.PopupMenu import android.widget.PopupMenu
import android.widget.RelativeLayout
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
import androidx.core.view.marginLeft
import androidx.core.view.marginTop
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.launcher.BuildConfig import com.simplemobiletools.launcher.BuildConfig
@ -68,11 +65,6 @@ class MainActivity : SimpleActivity(), FlingListener {
fragment.beVisible() fragment.beVisible()
} }
(home_screen_grid.layoutParams as RelativeLayout.LayoutParams).apply {
topMargin = statusBarHeight
bottomMargin = navigationBarHeight
}
if (!config.wasHomeScreenInit) { if (!config.wasHomeScreenInit) {
ensureBackgroundThread { ensureBackgroundThread {
getDefaultAppPackages() getDefaultAppPackages()
@ -248,17 +240,15 @@ class MainActivity : SimpleActivity(), FlingListener {
} }
fun homeScreenClicked(x: Float, y: Float) { fun homeScreenClicked(x: Float, y: Float) {
if (x >= home_screen_grid.left && x <= home_screen_grid.right && y >= home_screen_grid.top && y <= home_screen_grid.bottom) { val clickedGridItem = home_screen_grid.isClickingGridItem(getGridTouchedX(x), getGridTouchedY(y))
val clickedGridItem = home_screen_grid.isClickingGridItem(getGridTouchedX(x), getGridTouchedY(y)) if (clickedGridItem != null) {
if (clickedGridItem != null) { launchApp(clickedGridItem.packageName)
launchApp(clickedGridItem.packageName)
}
} }
} }
private fun getGridTouchedX(x: Float) = Math.min(Math.max(x.toInt() - home_screen_grid.marginLeft, 0), home_screen_grid.width) private fun getGridTouchedX(x: Float) = Math.min(Math.max(x.toInt(), 0), home_screen_grid.width)
private fun getGridTouchedY(y: Float) = Math.min(Math.max(y.toInt() - home_screen_grid.marginTop, 0), home_screen_grid.height) private fun getGridTouchedY(y: Float) = Math.min(Math.max(y.toInt(), 0), home_screen_grid.height)
fun showHomeIconMenu(x: Float, y: Float, gridItem: HomeScreenGridItem, isOnAllAppsFragment: Boolean) { fun showHomeIconMenu(x: Float, y: Float, gridItem: HomeScreenGridItem, isOnAllAppsFragment: Boolean) {
mLongPressedIcon = gridItem mLongPressedIcon = gridItem

View File

@ -5,12 +5,15 @@ import android.content.Context
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Color import android.graphics.Color
import android.graphics.Paint import android.graphics.Paint
import android.graphics.Rect
import android.text.Layout import android.text.Layout
import android.text.StaticLayout import android.text.StaticLayout
import android.text.TextPaint import android.text.TextPaint
import android.text.TextUtils import android.text.TextUtils
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import com.simplemobiletools.commons.extensions.navigationBarHeight
import com.simplemobiletools.commons.extensions.statusBarHeight
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.launcher.R import com.simplemobiletools.launcher.R
import com.simplemobiletools.launcher.extensions.getDrawableForPackageName import com.simplemobiletools.launcher.extensions.getDrawableForPackageName
@ -39,6 +42,8 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
private var gridCenters = ArrayList<Pair<Int, Int>>() private var gridCenters = ArrayList<Pair<Int, Int>>()
private var draggedItemCurrentCoords = Pair(-1, -1) private var draggedItemCurrentCoords = Pair(-1, -1)
var sideMargins = Rect() // apply fake margins at the home screen. Real ones would cause the icons be cut at dragging at screen sides
init { init {
textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply { textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.WHITE color = Color.WHITE
@ -52,6 +57,14 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
style = Paint.Style.STROKE 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() fetchGridItems()
} }
@ -98,7 +111,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
return return
} }
val center = gridCenters.minBy { Math.abs(it.first - x) + Math.abs(it.second - y) } val center = gridCenters.minBy { Math.abs(it.first - x + sideMargins.left) + Math.abs(it.second - y + sideMargins.top) }
var redrawIcons = false var redrawIcons = false
val gridCells = getClosestGridCells(center) val gridCells = getClosestGridCells(center)
@ -159,12 +172,16 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
return null return null
} }
fun getFakeWidth() = width - sideMargins.left - sideMargins.right
fun getFakeHeight() = height - sideMargins.top - sideMargins.bottom
@SuppressLint("DrawAllocation") @SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas) { override fun onDraw(canvas: Canvas) {
super.onDraw(canvas) super.onDraw(canvas)
if (rowXCoords.isEmpty()) { if (rowXCoords.isEmpty()) {
rowWidth = width / (COLUMN_COUNT) rowWidth = getFakeWidth() / COLUMN_COUNT
rowHeight = height / ROW_COUNT rowHeight = getFakeHeight() / ROW_COUNT
iconSize = rowWidth - 2 * iconMargin iconSize = rowWidth - 2 * iconMargin
for (i in 0 until COLUMN_COUNT) { for (i in 0 until COLUMN_COUNT) {
rowXCoords.add(i, i * rowWidth) rowXCoords.add(i, i * rowWidth)
@ -183,18 +200,19 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
gridItems.filter { it.drawable != null }.forEach { item -> gridItems.filter { it.drawable != null }.forEach { item ->
if (item.id != draggedItem?.id) { if (item.id != draggedItem?.id) {
val drawableX = rowXCoords[item.left] + iconMargin 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 // icons at the bottom are drawn at the bottom of the grid and they have no label
if (item.top == ROW_COUNT - 1) { if (item.top == ROW_COUNT - 1) {
val drawableY = rowYCoords[item.top] + rowHeight - iconSize - iconMargin * 2 val drawableY = rowYCoords[item.top] + rowHeight - iconSize - iconMargin * 2 + sideMargins.top
item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize) item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
} else { } else {
val drawableY = rowYCoords[item.top] + iconSize / 2 val drawableY = rowYCoords[item.top] + iconSize / 2 + sideMargins.top
item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize) item.drawable!!.setBounds(drawableX, drawableY, drawableX + iconSize, drawableY + iconSize)
if (item.id != draggedItem?.id) { if (item.id != draggedItem?.id) {
val textY = rowYCoords[item.top] + iconSize * 1.5f + labelSideMargin val textX = rowXCoords[item.left].toFloat() + labelSideMargin + sideMargins.left
val textY = rowYCoords[item.top] + iconSize * 1.5f + labelSideMargin + sideMargins.top
val staticLayout = StaticLayout.Builder val staticLayout = StaticLayout.Builder
.obtain(item.title, 0, item.title.length, textPaint, rowWidth - 2 * labelSideMargin) .obtain(item.title, 0, item.title.length, textPaint, rowWidth - 2 * labelSideMargin)
.setMaxLines(2) .setMaxLines(2)
@ -203,7 +221,7 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
.build() .build()
canvas.save() canvas.save()
canvas.translate(rowXCoords[item.left].toFloat() + labelSideMargin, textY) canvas.translate(textX, textY)
staticLayout.draw(canvas) staticLayout.draw(canvas)
canvas.restore() canvas.restore()
} }
@ -215,30 +233,39 @@ class HomeScreenGrid(context: Context, attrs: AttributeSet, defStyle: Int) : Vie
if (draggedItem != null && draggedItemCurrentCoords.first != -1 && draggedItemCurrentCoords.second != -1) { if (draggedItem != null && draggedItemCurrentCoords.first != -1 && draggedItemCurrentCoords.second != -1) {
// draw a circle under the current cell // draw a circle under the current cell
val center = gridCenters.minBy { Math.abs(it.first - draggedItemCurrentCoords.first) + Math.abs(it.second - draggedItemCurrentCoords.second) } 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 shadowX = rowXCoords[gridCells.first] + iconMargin.toFloat() + iconSize / 2 val shadowX = rowXCoords[gridCells.first] + iconMargin.toFloat() + iconSize / 2 + sideMargins.left
val shadowY = if (gridCells.second == ROW_COUNT - 1) { val shadowY = if (gridCells.second == ROW_COUNT - 1) {
rowYCoords[gridCells.second] + rowHeight - iconSize / 2 - iconMargin * 2 rowYCoords[gridCells.second] + rowHeight - iconSize / 2 - iconMargin * 2
} else { } else {
rowYCoords[gridCells.second] + iconSize rowYCoords[gridCells.second] + iconSize
} } + sideMargins.top
canvas.drawCircle(shadowX, shadowY.toFloat(), iconSize / 2f, dragShadowCirclePaint) canvas.drawCircle(shadowX, shadowY.toFloat(), iconSize / 2f, dragShadowCirclePaint)
} }
// show the app icon itself at dragging // show the app icon itself at dragging, move it above the finger a bit to make it visible
val drawableX = draggedItemCurrentCoords.first - iconSize val drawableX = (draggedItemCurrentCoords.first - iconSize / 1.5f).toInt()
val drawableY = draggedItemCurrentCoords.second - iconSize val drawableY = (draggedItemCurrentCoords.second - iconSize / 1.2f).toInt()
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)
} }
} }
// get the clickable area around the icon, it includes text too
private fun getClickableRect(item: HomeScreenGridItem): Rect {
val debugLeft = item.left * rowWidth + sideMargins.left
val debugTop = rowYCoords[item.top] + iconSize / 3 + sideMargins.top
return Rect(debugLeft, debugTop, debugLeft + rowWidth, debugTop + iconSize * 2)
}
fun isClickingGridItem(x: Int, y: Int): HomeScreenGridItem? { fun isClickingGridItem(x: Int, y: Int): HomeScreenGridItem? {
for (gridItem in gridItems) { for (gridItem in gridItems) {
if (x >= gridItem.left * rowWidth && x <= gridItem.right * rowWidth && y >= gridItem.top * rowHeight && y <= gridItem.bottom * rowHeight) { val rect = getClickableRect(gridItem)
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
return gridItem return gridItem
} }
} }

View File

@ -7,9 +7,7 @@
<com.simplemobiletools.launcher.views.HomeScreenGrid <com.simplemobiletools.launcher.views.HomeScreenGrid
android:id="@+id/home_screen_grid" android:id="@+id/home_screen_grid"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent" />
android:layout_marginStart="@dimen/icon_side_margin"
android:layout_marginEnd="@dimen/icon_side_margin" />
<include <include
android:id="@+id/all_apps_fragment" android:id="@+id/all_apps_fragment"