Fix race condition in rememberPageStateFixed
During screen rotation, currentPage could be updated to a wrong value. Split the rotation detection and scrolling to correct page to fix this issue. Fix: 281928661 Test: Manually with App languages page Change-Id: I71f69db0c832dc4b4dc90ee210efbfe768cf17e4
This commit is contained in:
@@ -21,14 +21,13 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material3.TabRow
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
@@ -50,7 +49,7 @@ fun SettingsPager(titles: List<String>, content: @Composable (page: Int) -> Unit
|
||||
|
||||
Column {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val pagerState by rememberPageStateFixed()
|
||||
val pagerState = rememberPageStateFixed()
|
||||
|
||||
TabRow(
|
||||
selectedTabIndex = pagerState.currentPage,
|
||||
@@ -89,17 +88,30 @@ fun SettingsPager(titles: List<String>, content: @Composable (page: Int) -> Unit
|
||||
*/
|
||||
@Composable
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
private fun rememberPageStateFixed(): State<PagerState> {
|
||||
private fun rememberPageStateFixed(): PagerState {
|
||||
var currentPage by rememberSaveable { mutableStateOf(0) }
|
||||
val pagerStateHolder = remember { mutableStateOf(PagerState(currentPage)) }
|
||||
LaunchedEffect(LocalConfiguration.current.orientation) {
|
||||
var targetPage by rememberSaveable { mutableStateOf(-1) }
|
||||
val pagerState = rememberPagerState()
|
||||
val configuration = LocalConfiguration.current
|
||||
var lastScreenWidthDp by rememberSaveable { mutableStateOf(-1) }
|
||||
val screenWidthDp = configuration.screenWidthDp
|
||||
LaunchedEffect(screenWidthDp) {
|
||||
// Reset pager state to fix an issue after configuration change.
|
||||
// When we declare android:configChanges="orientation" in the manifest, the pager state is
|
||||
// in a weird state after configuration change.
|
||||
pagerStateHolder.value = PagerState(currentPage)
|
||||
// When we declare android:configChanges in the manifest, the pager state is in a weird
|
||||
// state after configuration change.
|
||||
targetPage = currentPage
|
||||
lastScreenWidthDp = screenWidthDp
|
||||
}
|
||||
LaunchedEffect(targetPage) {
|
||||
if (targetPage != -1) {
|
||||
pagerState.scrollToPage(targetPage)
|
||||
targetPage = -1
|
||||
}
|
||||
}
|
||||
SideEffect {
|
||||
currentPage = pagerStateHolder.value.currentPage
|
||||
if (lastScreenWidthDp == screenWidthDp) {
|
||||
currentPage = pagerState.currentPage
|
||||
}
|
||||
}
|
||||
return pagerStateHolder
|
||||
return pagerState
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user