시배's Android

Compose | NestedScrollConnection not called animateScrollToItem 삽질기 본문

Android/Compose

Compose | NestedScrollConnection not called animateScrollToItem 삽질기

si8ae 2023. 9. 22. 17:01

이번 글에서는 animateScrollToItem or scrollToItem을 통해 특정 아이템으로 스크롤을 할 때 NestedScrollConnection 불려지지 않아 커스텀 된 TopAppBar의 상태가 변경되지 않는 문제로 삽질을 하다가, 구글의 의도를 알 수 있었고 조금은 cracky 한 방법으로 해결을 하였는 것을 공유하고자 합니다. 

 

문제의 발생

현재 저는 NetstedScrollConnection을 활용하여 scroll에 따라 특정 state를 변경시키며 이를 TopAppBar에 적용시켜 커스텀한 동작을하는 TopAppBar를 구현하여 사용 중에 있었습니다.

추후 요구사항이 추가되어 animateScrollToItem을 통해 최상단을 도달하게 하는 기능을 추가하고 나니 animateScrollToItem으로 NestedScrollConnection이 불리지 않아 TopAppBar에 state를 변경시키지 않아 원하는 동작을 확인할 수 없었습니다.

 

구글의 입장

문제를 해결하기 위해 구글링을 통해 Issue Tracker에 제기된 issue를 찾을 수 있었습니다. 

 

Google Issue Tracker

 

issuetracker.google.com

작년 7월 쯤 제기된 이슈에서

For now this is expected as nested scrolling is only activated through gesture based scrolling, not animation based scrolling. We do have plans to explore animation based nested scrolling in the future, so I'll keep you posted if things change.

제스처를 통한 스크롤과 애니메이션을 통한 스크롤을 별개로 보고 있다 보니 해당 이슈는 의도된 동작이지만 추후 수정할 계획이 있다는 입장을 확인할 수 있었습니다.

 

Google Issue Tracker

 

issuetracker.google.com

작년 12월에도 같은 이슈가 제기 되었고, 역시 구글에 입장은 아직까지는 제스처를 통한 스크롤과 애니메이션을 통한 스크롤을 별개로 보고 있어 NestedScrollDispatcher를 통해 문제를 해결할 수 있다고 알려주고 있었습니다.

val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
val dispatcher = NestedScrollDispatcher()
Scaffold(
    modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection, dispatcher),
    topBar = {...},
    content = { innerPadding ->
        ...
        LaunchedEffect(key1 = Unit, block = {
            coroutines.launch {
               delay(5000)
               // dispatch a scroll by a distance equal to the height offset limit of the top bar
               dispatcher.dispatchPreScroll(
                        Offset(0f, scrollBehavior.state.heightOffsetLimit),
                        NestedScrollSource.Fling)
                // Starts the scrollTo
                listState.animateScrollToItem(50, 0)

            }
        })

아쉽게도 해당방법으로는 동작하지 않는 것을 확인할 수 있었습니다.

 

해결책

animateToScrollToItem을 할 때 TopAppBarState를 초기화 하는 방식으로 해결하였습니다.

역시 compose는 xml과 다른 부분이 있다보니 아쉬운 점은 어쩔 수 없이 존재하는 거 같습니다 ㅠㅠ