Skip to content

Commit e09b441

Browse files
Refactor(UI): Improve app drawer context menu and keyboard behavior
This commit refactors the context menu logic in the app drawer to ensure only one menu is open at a time. Previously, multiple menus could be open simultaneously. The key changes are: * Replaced the `visibleHideLayouts` set with a single `openedContextMenuPosition` integer to track the currently open menu item. * The `ViewHolder` is now an inner class to access adapter properties. * When a new context menu is opened, any previously opened menu is now automatically closed by notifying the adapter of the change. * Clicking on another app item or the main layout now closes the open context menu. * Added padding to the bottom of the app and contact lists to account for the on-screen keyboard (IME), preventing it from covering list items. closes #989 closes #988
1 parent 16bec17 commit e09b441

File tree

3 files changed

+68
-21
lines changed

3 files changed

+68
-21
lines changed

app/src/main/java/com/github/codeworkscreativehub/mlauncher/ui/AppDrawerFragment.kt

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ import android.widget.TextView
2626
import androidx.annotation.RequiresApi
2727
import androidx.appcompat.widget.SearchView
2828
import androidx.core.net.toUri
29+
import androidx.core.view.ViewCompat
30+
import androidx.core.view.WindowInsetsCompat
2931
import androidx.core.view.isVisible
32+
import androidx.core.view.updatePadding
3033
import androidx.lifecycle.LiveData
3134
import androidx.lifecycle.MediatorLiveData
3235
import androidx.lifecycle.ViewModelProvider
@@ -88,6 +91,13 @@ class AppDrawerFragment : BaseFragment() {
8891
prefs.firstSettingsOpen = false
8992
}
9093

94+
ViewCompat.setOnApplyWindowInsetsListener(binding.mainLayout) { _, insets ->
95+
val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())
96+
binding.appsRecyclerView.updatePadding(bottom = imeInsets.bottom)
97+
binding.contactsRecyclerView.updatePadding(bottom = imeInsets.bottom)
98+
insets
99+
}
100+
91101
// Check if device is using gesture navigation or 3-button navigation
92102
val isGestureNav = isGestureNavigationEnabled(requireContext())
93103

@@ -115,10 +125,11 @@ class AppDrawerFragment : BaseFragment() {
115125

116126
sidebarContainer.layoutParams = layoutParams
117127

118-
searchSwitcher.setOnClickListener {
119-
switchMenus()
120-
}
121128
menuView.displayedChild = 0
129+
130+
mainLayout.setOnClickListener {
131+
appsAdapter.closeOpenedMenu()
132+
}
122133
}
123134

124135
// Retrieve the letter key code from arguments
@@ -248,7 +259,7 @@ class AppDrawerFragment : BaseFragment() {
248259
}
249260

250261
val contactAdapter = context?.let {
251-
parentFragment?.let { fragment ->
262+
parentFragment?.let { _ ->
252263
ContactDrawerAdapter(
253264
it,
254265
gravity,
@@ -313,8 +324,8 @@ class AppDrawerFragment : BaseFragment() {
313324

314325
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
315326
super.onScrollStateChanged(recyclerView, newState)
327+
appAdapter?.closeOpenedMenu()
316328
when (newState) {
317-
318329
RecyclerView.SCROLL_STATE_DRAGGING -> {
319330
onTop = !recyclerView.canScrollVertically(-1)
320331
if (onTop) {
@@ -414,7 +425,6 @@ class AppDrawerFragment : BaseFragment() {
414425
AppDrawerFlag.LaunchApp -> {
415426
setupProfileButtons(flag, viewModel, appAdapter, contactAdapter, profileType)
416427

417-
418428
binding.internetSearch.apply {
419429
isVisible = appListButtonFlags[0]
420430
setOnClickListener {
@@ -429,7 +439,12 @@ class AppDrawerFragment : BaseFragment() {
429439
"WORK", "PRIVATE" -> isVisible = false
430440
else -> {
431441
isVisible = appListButtonFlags[1]
432-
setOnClickListener { switchMenus() }
442+
setOnClickListener {
443+
switchMenus()
444+
binding.contactsRecyclerView.post {
445+
appsAdapter.closeOpenedMenu()
446+
}
447+
}
433448
}
434449

435450
}

app/src/main/java/com/github/codeworkscreativehub/mlauncher/ui/adapter/AppDrawerAdapter.kt

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ import com.github.codeworkscreativehub.mlauncher.helper.IconPackHelper.getSafeAp
4343
import com.github.codeworkscreativehub.mlauncher.helper.dp2px
4444
import com.github.codeworkscreativehub.mlauncher.helper.getSystemIcons
4545
import com.github.codeworkscreativehub.mlauncher.helper.utils.BiometricHelper
46-
import com.github.codeworkscreativehub.mlauncher.helper.utils.visibleHideLayouts
4746
import kotlinx.coroutines.CoroutineScope
4847
import kotlinx.coroutines.Dispatchers
4948
import kotlinx.coroutines.SupervisorJob
@@ -67,6 +66,7 @@ class AppDrawerAdapter(
6766

6867
private lateinit var prefs: Prefs
6968
private var appFilter = createAppFilter()
69+
private var openedContextMenuPosition = RecyclerView.NO_POSITION
7070
var appsList: MutableList<AppListItem> = mutableListOf()
7171
var appFilteredList: MutableList<AppListItem> = mutableListOf()
7272
private lateinit var binding: AdapterAppDrawerBinding
@@ -299,7 +299,7 @@ class AppDrawerAdapter(
299299
holder.clearIcon()
300300
}
301301

302-
class ViewHolder(
302+
inner class ViewHolder(
303303
itemView: AdapterAppDrawerBinding
304304
) : RecyclerView.ViewHolder(itemView.root) {
305305
val appHide: TextView = itemView.appHide
@@ -337,8 +337,8 @@ class AppDrawerAdapter(
337337
val contextMenuFlags = prefs.getMenuFlags("CONTEXT_MENU_FLAGS", "0011111")
338338

339339
// ----------------------------
340-
// 1️⃣ Hide optional layouts
341-
appHideLayout.isVisible = false
340+
// 1️⃣ Hide optional layouts (state-driven)
341+
appHideLayout.isVisible = absoluteAdapterPosition == openedContextMenuPosition
342342
appRenameLayout.isVisible = false
343343
appTagLayout.isVisible = false
344344

@@ -438,9 +438,12 @@ class AppDrawerAdapter(
438438

439439
appClose.setOnClickListener {
440440
appHideLayout.isVisible = false
441-
visibleHideLayouts.remove(absoluteAdapterPosition)
442-
val sidebarContainer = (context as? Activity)?.findViewById<View>(R.id.sidebar_container)
443-
if (visibleHideLayouts.isEmpty()) sidebarContainer?.isVisible = prefs.showAZSidebar
441+
openedContextMenuPosition = RecyclerView.NO_POSITION
442+
443+
val sidebarContainer = (context as? Activity)
444+
?.findViewById<View>(R.id.sidebar_container)
445+
446+
sidebarContainer?.isVisible = prefs.showAZSidebar
444447
}
445448

446449
// ----------------------------
@@ -485,9 +488,20 @@ class AppDrawerAdapter(
485488
if (openApp) {
486489
try {
487490
appDelete.alpha = if (context.isSystemApp(packageName)) 0.3f else 1f
491+
val currentPos = absoluteAdapterPosition
492+
493+
// Close previously opened menu
494+
if (openedContextMenuPosition != RecyclerView.NO_POSITION &&
495+
openedContextMenuPosition != currentPos
496+
) {
497+
notifyItemChanged(openedContextMenuPosition)
498+
}
499+
500+
// Open this one
488501
appHideLayout.isVisible = true
489502
sidebarContainer?.isVisible = false
490-
visibleHideLayouts.add(absoluteAdapterPosition)
503+
openedContextMenuPosition = currentPos
504+
491505
} catch (_: Exception) {
492506
}
493507
}
@@ -510,6 +524,14 @@ class AppDrawerAdapter(
510524
if (isPinned) updated.remove(packageName) else updated.add(packageName)
511525
prefs.pinnedApps = updated
512526
}
527+
528+
itemView.setOnClickListener {
529+
if (openedContextMenuPosition != RecyclerView.NO_POSITION &&
530+
openedContextMenuPosition != absoluteAdapterPosition
531+
) {
532+
this@AppDrawerAdapter.closeOpenedMenu()
533+
}
534+
}
513535
}
514536

515537

@@ -547,4 +569,14 @@ class AppDrawerAdapter(
547569
appTitle.setCompoundDrawables(null, null, null, null)
548570
}
549571
}
572+
573+
fun closeOpenedMenu() {
574+
if (openedContextMenuPosition != RecyclerView.NO_POSITION) {
575+
val oldPosition = openedContextMenuPosition
576+
openedContextMenuPosition = RecyclerView.NO_POSITION
577+
notifyItemChanged(oldPosition)
578+
// Redraw all visible items just in case
579+
notifyItemRangeChanged(0, itemCount)
580+
}
581+
}
550582
}

app/src/main/res/layout/adapter_app_drawer.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3-
xmlns:app="http://schemas.android.com/apk/res-auto"
4-
xmlns:tools="http://schemas.android.com/tools"
5-
android:layout_width="match_parent"
6-
android:layout_height="wrap_content"
7-
android:animateLayoutChanges="true">
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="wrap_content"
7+
android:animateLayoutChanges="true">
88

99
<FrameLayout
1010
android:id="@+id/appTitleFrame"
@@ -34,7 +34,7 @@
3434
android:gravity="end|center_vertical"
3535
android:paddingVertical="@dimen/app_padding_vertical"
3636
android:visibility="gone"
37-
tools:visibility="visible">
37+
tools:visibility="gone">
3838

3939
<!-- 1. Pin/Unpin -->
4040
<com.github.creativecodecat.components.views.FontAppCompatTextView

0 commit comments

Comments
 (0)