Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

안드로이드 앱 만들기 : jetpack compose 에서도 ConstraintLayout

Billcorea 2023. 3. 16. 15:17
반응형

https://developer.android.com/training/constraint-layout?hl=ko 

 

ConstraintLayout으로 반응형 UI 빌드  |  Android 개발자  |  Android Developers

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. ConstraintLayout으로 반응형 UI 빌드   Android Jetpack의 구성요소 ConstraintLayout을 사용하면 플랫 뷰 계층 구조(중첩

developer.android.com

 

 

ConstraintLayout

개발자 가이드를 읽어 봅니다.  눈 씌고 찾아보아도 jetpack compose에서 ui 구현하는 이야기는 없습니다.  이 layout  을 사용하는 이유는 개발자 가이드에서 설명하고 있는 것처럼 UI에 배치를 유연하게 하는 것이 목적일 수 있습니다. 

 

예전에 개발하던 xml 방식의 layout  파일에서는 배치 하고자 하는 항목들을 드래그해서 위치를 잡아 주는 것 만으로 유연하게 design을 할 수 있었습니다. 

 

jetpack compose 을 활용한 작업을 하는 동안에 그 생각이 났더랍니다. 유연하게 배치를 할 수 있는 방법이 뭐가 있을까 하고 말입니다. 

 

gradle 설정

 

// constraintlayout
implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha08"

개발자 가이드에도 나와 있기는 하지만, 잘 보이지 않았던 것입니다.  꼼꼼하게 읽어 보지도 않지만요.

아무튼 이번에 알게 되어 사용을 해 보았습니다. 

 

개발자 가이드에서 말하고 있는 것처럼 전체 화면에 배치를 하면서 이전 배치한 요소의 하단에  다음 배치할 요소를 연결하는 방식으로 배치할 수 있는 데 compose에서는 어떻게 그것을 구현했을 까요?

 

    val configuration = LocalConfiguration.current
    val screenWidth = configuration.screenWidthDp.dp
    val screenHeight = configuration.screenHeightDp.dp

    ConstraintLayout {
        // 배치 되는 요소들의 목록 집합
        val (runBtn, passwordEntry) = createRefs()

        if (packCheck.value) {
            Row(
                modifier = Modifier
                    .constrainAs(runBtn) {  // 위치 지정해 보기
                        top.linkTo(parent.top, margin = 50.dp)
                        start.linkTo(parent.start, margin = (screenWidth * 0.8f).value.dp)
                        end.linkTo(parent.end, margin = 50.dp)
                    },
            ) {
                TextButton(onClick = {
                    doRunApk(runApkInfo)
                }) {
                    Image(
                        modifier = Modifier
                            .width(100.dp)
                            .height(100.dp),
                        painter = painterResource(id = R.drawable.ic_runapp_png),
                        contentDescription = "run Order App",
                    )
                }
            }
        }

        Row(
            modifier = Modifier
                .constrainAs(passwordEntry) { // 위치 지정해 보기
                    top.linkTo(parent.top, margin = screenHeight * .4f)
                    start.linkTo(parent.start, margin = (screenWidth * .4f).value.dp)
                }
        ) {
            OutlinedTextField(
                modifier = Modifier
                    .padding(3.dp)
                    .width(250.dp),
                value = password,
                onValueChange = {
                    password = it.replace("[^0-9]".toRegex(), "")
                    Log.e("", "password=$password")
                    if (password.length == 4) {
                        doPasswordCheck(password)
                        password = ""
                    }
                },
                placeholder = {
                    Text(text = stringResource(id = R.string.msgEnterPassword))
                },
                singleLine = true,
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword),
                visualTransformation = PasswordVisualTransformation(),
                textStyle = typography.displayLarge
            )
        }
    }

제일 바깥쪽에 ConstraintLayout 로 감싸고 그 안에 배치할 것을 추가합니다. 예제에서는 2개의 요소만 배치를 했기 때문에  선언된 것도 2개뿐 입니다만, 여러 개 있다면 그것들을 다 기술해 주어야 합니다. 그리고 각 요소들의 Modifier.constrainAs을 활용하여 위치 지정을 시작합니다. 

 

예제에서는 parent 라고 기술되는 제일 상위 ConstraintLayout으로부터 위치만 지정하도록 구성을 해 보았지만, parent 대신에 이전 요소인 runBtn 등의 이름이 적용될 수 도 있습니다. 

 

이제는 화면 전체에 자유자재로 요소들을 배치하여 유연한 UI도 만들어 볼 수 있을 듯 합니다. 

 

배치 예시

 

반응형