Fix glitchy nav drawer scrolling when opening (#848)

## Description
The nav drawer would always glitch a little when it gained focus due it
to trying to keep the selected page in view. #842 made this even worst.

This PR fixes that issue by hoisting the list scroll state up higher
which ensures it is remembered between recompositions. This change also
eliminates the need for workarounds to try and scroll it
programmatically which is also a tiny performance boost.

### Related issues
Follow up to #842 

### Testing
Emulator & nvidia shield

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-02-08 16:21:38 -05:00 committed by GitHub
parent 72e5e6ae86
commit 63b37ef3f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 6 additions and 32 deletions

View file

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.rememberSerializable
@ -231,6 +232,7 @@ fun ApplicationContent(
)
}
}
val navDrawerListState = rememberLazyListState()
NavDisplay(
backStack = navigationManager.backStack,
onBack = { navigationManager.goBack() },
@ -257,6 +259,7 @@ fun ApplicationContent(
user = user,
server = server,
drawerState = drawerState,
navDrawerListState = navDrawerListState,
onClearBackdrop = viewModel::clearBackdrop,
modifier = Modifier.fillMaxSize(),
)

View file

@ -18,8 +18,8 @@ import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.Home
@ -41,7 +41,6 @@ import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
@ -88,12 +87,10 @@ import com.github.damontecres.wholphin.ui.spacedByWithFooter
import com.github.damontecres.wholphin.ui.theme.LocalTheme
import com.github.damontecres.wholphin.ui.toServerString
import com.github.damontecres.wholphin.ui.tryRequestFocus
import com.github.damontecres.wholphin.util.ExceptionHandler
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.imageApi
@ -272,6 +269,7 @@ fun NavDrawer(
user: JellyfinUser,
server: JellyfinServer,
drawerState: DrawerState,
navDrawerListState: LazyListState,
onClearBackdrop: () -> Unit,
modifier: Modifier = Modifier,
viewModel: NavDrawerViewModel =
@ -320,8 +318,6 @@ fun NavDrawer(
visibilityThreshold = IntOffset.VisibilityThreshold,
),
)
val config = LocalConfiguration.current
val heightInPx = remember { with(density) { config.screenHeightDp.dp.roundToPx() } }
ModalNavigationDrawer(
modifier = modifier,
@ -329,28 +325,8 @@ fun NavDrawer(
drawerContent = { drawerValue ->
val isOpen = drawerValue.isOpen
val spacedBy = 4.dp
val listState = rememberLazyListState()
val searchFocusRequester = remember { FocusRequester() }
suspend fun scrollToSelected() {
val target = selectedIndex + 2
try {
if (target !in
listState.firstVisibleItemIndex..<listState.layoutInfo.visibleItemsInfo.lastIndex
) {
val mult =
if ((target - 2) < listState.layoutInfo.totalItemsCount / 2) -1 else 1
listState.animateScrollToItem(selectedIndex + 2, mult * (heightInPx / 2))
}
} catch (ex: Exception) {
Timber.w(ex, "Error scrolling to %s", target)
}
}
LaunchedEffect(selectedIndex) {
scrollToSelected()
}
ProvideTextStyle(MaterialTheme.typography.labelMedium) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
@ -374,7 +350,7 @@ fun NavDrawer(
modifier = Modifier,
)
LazyColumn(
state = listState,
state = navDrawerListState,
contentPadding = PaddingValues(0.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedByWithFooter(spacedBy),
@ -389,11 +365,6 @@ fun NavDrawer(
focusRequester.tryRequestFocus()
}
}
onExit = {
scope.launch(ExceptionHandler()) {
scrollToSelected()
}
}
}.fillMaxHeight(),
) {
item {