summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Sierd de Vries <contact@lecapuchon.nl>2026-08-12 15:46:22 +0200
committerDirk Sierd de Vries <contact@lecapuchon.nl>2026-08-12 15:46:22 +0200
commit24cead725ddb0d601516399398d634cbfda0dec1 (patch)
treee357e3806de87af997d55b81905f17305dbf82f9
parent1d1a57ae60c973439bd3ad0bd11bb72f3331c3ad (diff)
downloadSidePhOnelauncher-24cead725ddb0d601516399398d634cbfda0dec1.tar.gz
SidePhOnelauncher-24cead725ddb0d601516399398d634cbfda0dec1.tar.bz2
SidePhOnelauncher-24cead725ddb0d601516399398d634cbfda0dec1.zip
Fix app drawer DPAD focus navigation
-rw-r--r--app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt14
-rw-r--r--app/src/main/java/app/sidephonelauncher/ui/AppDrawerFragment.kt37
2 files changed, 50 insertions, 1 deletions
diff --git a/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt b/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt
index c0186ba..9bc0da2 100644
--- a/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt
+++ b/app/src/main/java/app/sidephonelauncher/ui/AppDrawerAdapter.kt
@@ -41,6 +41,7 @@ class AppDrawerAdapter(
private val appRenameListener: (AppModel, String) -> Unit,
private val appLeftListener: () -> Boolean = { false },
private val appBackListener: () -> Boolean = { false },
+ private val appVerticalFocusListener: (Int, Int) -> Boolean = { _, _ -> false },
private val privateSpaceToggleListener: () -> Unit = {},
private val privateSpaceSettingsListener: () -> Unit = {},
) : ListAdapter<AppModel, RecyclerView.ViewHolder>(DIFF_CALLBACK), Filterable {
@@ -142,6 +143,7 @@ class AppDrawerAdapter(
appRenameListener,
appLeftListener,
appBackListener,
+ appVerticalFocusListener,
)
is SpacerViewHolder -> Unit
@@ -275,6 +277,7 @@ class AppDrawerAdapter(
appRenameListener: (AppModel, String) -> Unit,
appLeftListener: () -> Boolean,
appBackListener: () -> Boolean,
+ appVerticalFocusListener: (Int, Int) -> Boolean,
) = with(binding) {
appHideLayout.visibility = View.GONE
renameLayout.visibility = View.GONE
@@ -351,6 +354,17 @@ class AppDrawerAdapter(
if (event.action == KeyEvent.ACTION_DOWN) appLeftListener() else false
}
+ KeyEvent.KEYCODE_DPAD_UP,
+ KeyEvent.KEYCODE_DPAD_DOWN -> {
+ if (event.action != KeyEvent.ACTION_DOWN) return@setOnKeyListener true
+ val direction = if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) 1 else -1
+ val position = bindingAdapterPosition
+ if (position == RecyclerView.NO_POSITION) true else appVerticalFocusListener(
+ position,
+ direction
+ )
+ }
+
KeyEvent.KEYCODE_BACK -> {
when (event.action) {
KeyEvent.ACTION_DOWN -> true
diff --git a/app/src/main/java/app/sidephonelauncher/ui/AppDrawerFragment.kt b/app/src/main/java/app/sidephonelauncher/ui/AppDrawerFragment.kt
index a831807..bc134a9 100644
--- a/app/src/main/java/app/sidephonelauncher/ui/AppDrawerFragment.kt
+++ b/app/src/main/java/app/sidephonelauncher/ui/AppDrawerFragment.kt
@@ -361,6 +361,7 @@ class AppDrawerFragment : Fragment() {
focusSearchInput()
true
},
+ appVerticalFocusListener = ::moveFocusFromPosition,
privateSpaceToggleListener = {
viewModel.togglePrivateSpaceLock()
},
@@ -470,13 +471,47 @@ class AppDrawerFragment : Fragment() {
dismissSearchInput()
binding.recyclerView.requestFocus()
+ focusRecyclerItem(position)
+ return true
+ }
+
+ private fun moveFocusFromPosition(currentPosition: Int, direction: Int): Boolean {
+ val targetPosition = findNextFocusablePosition(currentPosition, direction)
+ if (targetPosition == RecyclerView.NO_POSITION) {
+ if (direction < 0) {
+ focusSearchInput()
+ }
+ return true
+ }
+
+ binding.recyclerView.requestFocus()
+ focusRecyclerItem(targetPosition)
+ return true
+ }
+
+ private fun findNextFocusablePosition(currentPosition: Int, direction: Int): Int {
+ var targetPosition = currentPosition + direction
+ while (targetPosition in 0 until adapter.itemCount) {
+ val appModel = adapter.appFilteredList.getOrNull(targetPosition)
+ if (appModel != null
+ && appModel !is AppModel.PrivateSpaceHeader
+ && appModel !is AppModel.Spacer
+ && appModel.appPackage.isNotBlank()
+ ) {
+ return targetPosition
+ }
+ targetPosition += direction
+ }
+ return RecyclerView.NO_POSITION
+ }
+
+ private fun focusRecyclerItem(position: Int) {
binding.recyclerView.scrollToPosition(position)
binding.recyclerView.post {
val holder = binding.recyclerView.findViewHolderForAdapterPosition(position)
val itemView = holder?.itemView?.findViewById<View>(R.id.appRow) ?: holder?.itemView
itemView?.requestFocus()
}
- return true
}
private fun initClickListeners() {