본문 바로가기
Android/Kotlin

[Compose] Compose Image center crop not working

by DnaJ 2023. 5. 15.
반응형

이미지를 배경으로 설정 하려고 했지만

이미지 사이즈가 변경 되지도 않고 Center Crop 속성이 적용되지 않는 버그가 있었다.

 

재현되는 버전

  • Compose Compiler Version : 1.4.4
  • Compose Version : 1.4.0

 

https://play.google.com/store/apps/details?id=com.danchoo.tagalbum&hl=ko

 

태그앨범 - Google Play 앱

사진과 앨범을 태그로 관리하세요. 결혼식, 팬클럽, 동호회등 원하는 카테고리를 만들어 정리해보세요. 사진에 태그를 설정하여 손쉽게 찾아보세요!

play.google.com

 

배경으로는 설정을 해야 하고 이미지의 height 가 Component 보다 커지는 이상한? 버그가 있었다.

 

ConstraintLayout 도 사용해봤고

BoxWithConstraint 도 사용해 봤고

IntrinsicSize.Min 으로도 해봤고.... 다 안되었다.

 

마지막으로 찾은 방법이 

Contents 의 height 를 계산하여 height 를 맞춰주는 것!!!

 

예시의 Contents 는 Colum 으로 구성이 되어있다.

 

 

Colum 의 높이를 구한다음 image의 높이를 셋팅해준다.

코드는 아래와 같다.

 

onGloballyPositioned 으로 size 가 변경될때 마다 높이를 계산하여 준다.

remember 를 사용하여 height 가 변경될때 마다 image 가 높이를 변경 할 수 있도록 설정해준다.

 

https://smartstore.naver.com/happysiso

 

해피시소마켓 : 네이버쇼핑 스마트스토어

SISO

smartstore.naver.com

 

@Composable
fun Test(
    modifier: Modifier = Modifier
) {
    val height = remember { mutableStateOf(0.dp) }
    val localDensity = LocalDensity.current

    Box(
        modifier = modifier
            .fillMaxWidth()
            .wrapContentHeight()
    ) {
        Image(
            modifier = Modifier
                .fillMaxWidth()
                .height(height.value),
            painter = painterResource(id = R.drawable.background_temp),
            contentScale = ContentScale.Crop,
            contentDescription = ""
        )

        Column(
            modifier = Modifier
                .fillMaxWidth()
                .wrapContentHeight()
                .onGloballyPositioned { coordinates ->
                    height.value = with(localDensity) { coordinates.size.height.toDp() }
                },
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {

            // contents...
        }
    }
}

 

 

onGloballyPositioned

/**
 * Invoke [onGloballyPositioned] with the [LayoutCoordinates] of the element when the
 * global position of the content may have changed.
 * Note that it will be called **after** a composition when the coordinates are finalized.
 *
 * This callback will be invoked at least once when the [LayoutCoordinates] are available, and every
 * time the element's position changes within the window. However, it is not guaranteed to be
 * invoked every time the position _relative to the screen_ of the modified element changes. For
 * example, the system may move the contents inside a window around without firing a callback.
 * If you are using the [LayoutCoordinates] to calculate position on the screen, and not just inside
 * the window, you may not receive a callback.
 *
 * Usage example:
 * @sample androidx.compose.ui.samples.OnGloballyPositioned
 */
@Stable
fun Modifier.onGloballyPositioned(
    onGloballyPositioned: (LayoutCoordinates) -> Unit
) = this.then(
    OnGloballyPositionedModifierImpl(
        callback = onGloballyPositioned,
        inspectorInfo = debugInspectorInfo {
            name = "onGloballyPositioned"
            properties["onGloballyPositioned"] = onGloballyPositioned
        }
    )
)
콘텐츠의 전역 위치가 변경되었을 수 있는 경우 요소의 LayoutCoordinates로 onGloballyPositioned를 호출합니다. 좌표가 확정되면 컴포지션 후에 호출됩니다. 이 콜백은 LayoutCoordinates를 사용할 수 있을 때 한 번 이상 호출되고 창 내에서 요소의 위치가 변경될 때마다 호출됩니다. 단, 수정된 요소의 화면 기준 위치가 변경될 때마다 호출된다는 보장은 없습니다. 예를 들어, 시스템은 콜백을 실행하지 않고 창 내부의 내용을 이동할 수 있습니다. LayoutCoordinates를 사용하여 창 내부뿐만 아니라 화면의 위치를 ​​계산하는 경우 콜백을 받지 못할 수 있습니다.
반응형

댓글