Android/Compose

[Compose] TextField, Scaffold, SnackBar

쏭식 2022. 9. 21. 23:59

이 글에서는 TextField를 만들어, 현재 입력하고 있는 값에서 버튼을 누르면 입력했던 값이 SnackBar형태로 나오는 간단한 프로그램을 짜보자.

결과화면

Scaffold(
                scaffoldState = scaffoldState //스낵바를 활용하기위해
            ) {
                Column(
                    modifier = Modifier.fillMaxSize(),
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally,
                ){
                    TextField(
//                    value = textValue.value, //비어있으면 입력이 안됨(값이 변하지 않기 때문에)
//                    onValueChange = {
//                        textValue.value = it
//                    } //값이 변했을 때의 함수
                        value = text,
                        onValueChange = setValue,
                    )
                    Button(onClick = {
                        keyboardController?.hide()
                        scope.launch {
                            scaffoldState.snackbarHostState.showSnackbar("Hello $text")
                        }
                    }) {
                        Text("클릭")
                    }
                }
            }

먼저 뷰에 해당하는 Column부분을 살펴보자.

앞에서 했던 것과 같이 modifier를 통해 사이즈를 정해주고,

각각 vertical, horizontal을 사용하여 위치를 위와 같이 지정해주었다.

 

그 다음 입력할 수 있는 TextField 부분을 살펴보자.

처음에는 value 값을 초기값으로 " " 이렇게 빈 칸을 설정해 놓는다면 아무리 입력해도 Field값이 변하지 않기 때문에

입력하는 것처럼 보이지 않게 된다.

 

따라서 우리는 이 때 우리가 입력하는 값을 value에 지정하여 유동적으로 값이 변하게 해야한다.

//            val textValue = remember{
//                mutableStateOf("")
//            }
//                    value = textValue.value, //비어있으면 입력이 안됨(값이 변하지 않기 때문에)
//                    onValueChange = {
//                        textValue.value = it
//                    } //값이 변했을 때의 함수

첫 번째는 변수로 textValue값을 계속 기억할 수 있게 remember형태로 기록하는 것이다.

이렇게 한 다음 해당 value값을 현재 입력되고 있는 값의 value로 지정해 두는 것이다.

이 때 onValueChange로 해당 값이 변할 때 마다 textValue에 저장하게 된다면 value의 값도 변하게 될 것이기 때문에 

입력하는 것처럼 해당 뷰가 설정될 수 있다. 

 

하지만 여기서 코틀린의 구조분해를 사용하여 더욱 간편하게 설정할 수 있다.

val (text, setValue) = remember{
    mutableStateOf("")
    //text : String, setValue : (String) -> Unit 을 리턴하는 형태
    //값을 다시 할당하는 setter에 해당하게 됨
}

MutableState를 들어가보면 밑의 사진과 같이 구조분해를 할 수 있께 나타나있다.

따라서 위의 코드처럼 text, setValue를 통해 하나는 String, 하나는 String에서 Unit을 반환하는 형태로 분해하였다.

                    TextField(
//                    value = textValue.value, //비어있으면 입력이 안됨(값이 변하지 않기 때문에)
//                    onValueChange = {
//                        textValue.value = it
//                    } //값이 변했을 때의 함수
                        value = text,
                        onValueChange = setValue,
                    )

따라서 TextField를 위와 같이 value 값을 현재 text, onValueChange에는 text를 변환시키는 setValue를 넣어 text의 값을 변화시켜 value의 값에 집어넣어 똑같은 기능을 구현하였다.

Button(onClick = {
    keyboardController?.hide()
    scope.launch {
        scaffoldState.snackbarHostState.showSnackbar("Hello $text")
    }
}) {
    Text("클릭")
}

다음 버튼이다. 버튼을 눌렀을 때 scaffoldState가 있는데, 스낵바, 탑바, 바텀바 등 을 이용하기 위해선 최근 화면의 상태를 기억하는 Scaffold로 감싸주어야한다. 

val scaffoldState = rememberScaffoldState() //최근의 상태를 지정
val scope = rememberCoroutineScope()

이렇게 rememberScaffoldState를 통해 최근 상태를 기억하는 것을 상태에 집어넣어준다.

 

위에서 코루틴스코프를 사용한 이유는 showSnackbar가 suspend로 되어있기 때문에 이 또한 remember코루틴 스코프를 통해 해당 함수를 실행해주어야한다.

 

또한, 버튼을 클릭하였을 때 해당 키보드를 바로 숨겨주기 위해

val keyboardController = LocalSoftwareKeyboardController.current

키보드컨트롤러를 버튼이 클릭하였을 때 hide()하여 숨겨주면 끝!!

 

 

GitHub - SsongSik/Jetpack_Compose: Creating apps using Jetpack Compose

Creating apps using Jetpack Compose. Contribute to SsongSik/Jetpack_Compose development by creating an account on GitHub.

github.com