박종훈 기술블로그

[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