https://kotlinlang.org logo
#compose
Title
# compose
r

Rick Regan

12/03/2021, 3:49 PM
I want to remember scroll state across configuration changes within a Text with modifier
.verticalScroll(scrollState)
. •
val scrollState = rememberScrollState()
does not survive a configuration change. •
val scrollState = rememberSaveable { ScrollState(0) }
gets an exception "ScrollState@fb46372 cannot be saved using the current SaveableStateRegistry". •
val scrollState = ScrollState(0)
globally outside of any Composable works, but this is putting the scroll state outside the scope of the Composable. Is it OK to do that? Is there another way?
i

Ian Lake

12/03/2021, 4:40 PM
rememberScrollState
uses
rememberSaveable
internally, so it certainly does save and restore its state after a config change: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt;l=81
r

Rick Regan

12/03/2021, 4:42 PM
Hmmm, thanks. It did not work for me...I'll try it again with a minimal repro.
i

Ian Lake

12/03/2021, 4:43 PM
Is what you're trying to scroll also immediately available after a config change? If there's a composition with no data, then that restored scroll position is going to be reset to the max available (i.e., to the top if there's no content at all)
r

Rick Regan

12/03/2021, 4:46 PM
I have a fixed height
Text
that I've scrolled down into. When I rotate, the text is still there and in its proper scroll position when I use the third option.
rememberScrollState
does work in a small example, but not in my app. I'll keep looking into it...
I know what it is. I use the same element in both configurations, with logic like
Copy code
if (maxWidth < 500.dp) {
  MyComposable()
} else {
  MyComposable()
}
So each one gets its own fresh
ScrollState
. (The text they display is in my app state.) To fix it, I have to hoist
rememberScrollState
. If I put it in that top-level composable then I have to pass it down through many layers of composables (not shown). That makes option 3 above (
val scrollState = ScrollState(0)
in my app state) more appealing. But is that bad practice?
i

Ian Lake

12/03/2021, 6:38 PM
Well, option 3 won't actually help with process death and recreation (i.e., what you test when you enable the 'Don't keep activties' developer option); you really do need to save it and restore it at some level
State hoisting is a natural part of Compose: https://developer.android.com/jetpack/compose/state#state-hoisting
r

Rick Regan

12/03/2021, 7:50 PM
Thanks, I was overlooking process death (which is down there on my todo list 🙂 ). Obviously then I'll also have to save the accompanying text with
rememberSaveable
. I have the text as
text by mutableStateOf()
 in my "view model" (not actually ViewModel); so looking ahead: is
rememberSaveable(text) { text }
(at an appropriate-level composable) the way to do it so that it keeps updating the "save"?
i

Ian Lake

12/03/2021, 8:26 PM
If that text hasn't been actually persisted to disk, yep, you'll want to use
rememberSaveable
r

Rick Regan

12/03/2021, 8:27 PM
Thanks so much for the help.
109 Views