박종훈 기술블로그

[Jetpack Compose] nestedScroll connection 을 이용하여 스크롤 시에 AppTopBar를 사라졌다 보였다 하게 하기


Gmail 앱의 경우 AppTopBar가 위와 같이 아래로 스크롤 할 경우에는 사라졌다가 위로 스크롤 할 경우에는 다시 보이게 처리가 되어있다.

나도 이렇게 처리하고 싶었어서 어떻게 구현해야하는지 찾아보려고 했는데 생각만큼 잘 나오지 않았어서 한참을 고생했다.
정확하게 이 기능을 뭐라 해야할지 모르겠어서 더 그랬을지도 모르겠다.

아무튼 이에 정리해본다.

아래 코드는 jetpack compose - material m3 기준으로 작성하였다.

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainPage() {
    val topAppBarHeight = 64.dp
    val topAppBarHeightPx = with(LocalDensity.current) { topAppBarHeight.roundToPx().toFloat() }
    val topAppBarOffsetHeightPx = remember { mutableStateOf(0f) }

    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {

                val delta = available.y
                val newOffset = topAppBarOffsetHeightPx.value + delta
                topAppBarOffsetHeightPx.value = newOffset.coerceIn(-topAppBarHeightPx, 0f)

                return Offset.Zero
            }
        }
    }

    Scaffold(
        modifier = Modifier.nestedScroll(nestedScrollConnection),
        topBar = {
            TopAppBar(title = { "TopAppBar" },
                modifier = Modifier.offset {
                    IntOffset(
                        x = 0, y = topAppBarOffsetHeightPx.value.roundToInt()
                    )
                })
        },
        containerColor = MaterialTheme.colorScheme.background,
        content = {
            /* Your Content */
        })
}

이후 content에서 상단에 64dp 만큼 여백을 주어야 컨텐츠가 숨겨지지 않는다.

[관련 키워드]
jetpack, compose, Appbar, AppTopBar, TopBar, Toolbar, nestedScroll, connection