Compose의 노출 추적

UI 요소가 화면에 표시되는 시점을 추적하면 분석 로깅, UI 상태 관리, 동영상 콘텐츠 자동 재생 또는 일시중지를 통한 리소스 최적화 등 다양한 사용 사례에 도움이 됩니다. Compose는 다음과 같은 UI 요소 공개 상태를 추적하는 여러 수정자를 제공합니다.

  • onVisibilityChanged - 이 수정자는 컴포저블의 공개 상태가 변경될 때 알려줍니다. 이는 컴포저블이 표시될 때마다 작업이나 부작용을 트리거하는 데 적합합니다.
  • onLayoutRectChanged - 이 수정자는 루트, 창, 화면을 기준으로 컴포저블의 경계에 관한 정보를 제공합니다. 하위 수준 제어를 제공하며 onVisibilityChanged의 기반 API입니다. 이 수정자는 onGloballyPositioned와 유사하지만 성능이 더 우수하고 유연성이 향상되었습니다.

이러한 API는 수정자 체인의 일부로 모든 컴포저블과 함께 사용할 수 있습니다.

onVisibilityChanged로 공개 상태 변경사항 추적

항목이 사용자에게 표시되거나 부분적으로 표시되는 시점을 이해하면 분석을 추적하거나 (예: 조회수) 성능을 최적화하거나(항목이 표시될 때만 네트워크에서 데이터를 가져오거나 미리 가져옴) 이벤트를 트리거 (동영상 재생 또는 일시중지)하는 데 도움이 될 수 있습니다.

항목의 공개 상태가 변경될 때 알림을 받으려면 다음 예와 같이 onVisibilityChanged 수정자를 사용합니다.

Text(
    text = "Some text",
    modifier = Modifier
        .onVisibilityChanged { visible ->
            if (visible) {
                // Do something if visible.
            } else {
                // Do something if not visible.
            }
        }
        .padding(vertical = 8.dp)
)

onVisibilityChanged 수정자는 컴포저블의 현재 공개 상태를 반영하는 불리언 값을 제공합니다. 또한 minFractionVisible 및 minDurationMs와 같은 매개변수를 제공하므로 공개 상태 콜백을 트리거해야 하는 시점을 더 세밀하게 제어할 수 있습니다.

다른 모든 수정자와 마찬가지로 onVisibilityChanged 수정자에서도 순서가 중요합니다. 위 예는 패딩이 있는 텍스트를 렌더링하는 컴포저블 함수를 보여줍니다. 수정자가 패딩과 함께 전체 컴포저블에 영향을 미치도록 하려면 padding 수정자 앞에 onVisibilityChanged 수정자를 추가합니다.

표시 콜백을 트리거하기 전에 컴포저블에 시간 제한 설정

경우에 따라 항목이 일정 시간 동안 사용자에게 표시된 후에만 작업을 트리거해야 할 수 있습니다. 예를 들어 동영상이 사용자에게 일정 시간 동안 표시된 경우 동영상을 자동재생할 수 있습니다.

정의된 기간 동안 항목이 표시된 후 작업을 트리거하려면 onVisibilityChanged 수정자의 minDurationMs 매개변수를 사용합니다. 이 매개변수는 콜백이 트리거되기 위해 컴포저블이 지속적으로 표시되어야 하는 최소 시간을 지정합니다. 지속 시간이 충족되기 전에 컴포저블이 표시되지 않으면 타이머가 재설정됩니다. 기본값은 0밀리초입니다.

다음 스니펫은 컴포저블이 사용자에게 3초 동안 표시된 후 배경을 보라색으로 변경합니다.

var background by remember { mutableStateOf(PalePink) }
Card(
    modifier = modifier
        // ...
        .onVisibilityChanged(minDurationMs = 3000) {
            if (it) {
                background = MutedPlum
            }
        }
) {

    Box(
        modifier = Modifier
            // ...
            .background(background),
        contentAlignment = Alignment.Center,
    ) {
        // ...
    }
}

그림 1. 컴포저블이 화면에 3초 동안 계속 표시되면 배경이 분홍색에서 자두색으로 변경됩니다.

최소 표시 비율 설정

컴포저블의 공개 상태 콜백에 최소 표시 비율을 설정하면 스크롤 가능한 콘텐츠 (예: LazyColumn)를 사용할 때 화면 크기를 초과하는 항목의 데이터 가져오기를 최적화하는 데 유용합니다.

이러한 경우 onVisibilityChanged 수정자의 minFractionVisible 매개변수를 사용하여 컴포저블이 표시된 것으로 표시되기 위해 화면에 표시되어야 하는 비율을 정의합니다. 0.0f에서 1.0f 사이의 부동 소수점 값을 지원하며 기본적으로 1.0f로 설정됩니다. 1.0f는 컴포저블이 화면에 완전히 표시되거나 표시 영역보다 큰 경우 전체 표시 영역을 채워야 함을 의미합니다.

표시되는 부분이 minFractionVisible보다 크거나 컴포저블이 완전히 표시되거나 표시 영역을 채우면 콜백은 true를 수신합니다. 그렇지 않으면 false를 수신합니다.

LazyColumn(
    modifier = modifier.fillMaxSize()
) {
    item {
        Box(
            modifier = Modifier
                // ...
                // Here `visible` is `true` when more than 20% of the composable is visible.
                .onVisibilityChanged(
                    minFractionVisible = 0.2f,
                ) { visible ->
                    if (visible) {
                        // Call specific logic here.
                        // viewModel.fetchDataFromNetwork()
                    }
                }
                .padding(vertical = 16.dp)
        ) {
            Text(
                text = "Sample Text",
                modifier = Modifier.padding(horizontal = 16.dp)
            )
        }
    }
}

그림 2. minFractionVisible가 설정되지 않은 경우 그림 3. minFractionVisible를 0.2f로 설정합니다.

앞서 사용한 예에서는 컴포저블이 완전히 표시되기 전에 네트워크에서 Androidify 봇을 미리 로드합니다. 그림 2에서 세 번째 봇은 컴포저블이 완전히 표시되지 않으므로 로드되지 않습니다. 그림 3에서는 minFractionVisible가 설정되어 있으며 세 번째 봇이 화면에 완전히 표시되기 전에 로드됩니다.

컴포저블 숨기기 및 공간 유지

주변 레이아웃을 변경하지 않고 컴포저블을 숨기려면 visible 수정자를 사용합니다. false를 전달하면 컴포저블이 계속 측정되지만 배치되거나 그려지지는 않습니다. alpha를 0f로 설정하는 것과 달리 visible(false)는 접근성 트리에서 요소를 삭제하고 터치 상호작용을 사용 중지하면서 레이아웃 공간을 유지합니다.

다음 예는 숨겨져 있는 동안 공간을 유지하는 체크 아이콘을 보여주므로 옆에 있는 텍스트가 이동하지 않습니다.

Row(modifier, verticalAlignment = Alignment.CenterVertically) {
    Icon(
        painter = painterResource(R.drawable.check),
        contentDescription = "Saved",
        modifier = Modifier
            // The icon keeps its space while it's hidden, so the text doesn't move.
            .visible(isSaved)
    )
    Text("Draft", Modifier.padding(start = 8.dp))
}

컴포저블이 표시되고 사라질 때 컴포저블 주변의 레이아웃이 이동하지 않아야 하는 경우 visible를 사용합니다. 컴포저블과 그 공간을 삭제하려면 호출하지 않거나 AnimatedVisibility를 사용하여 애니메이션을 적용합니다.