안드로이드 앱 개발 공부/jetpack Compose

JetPack Compose_Scaffold, TextField, Button, 구조분해, SnackBar, 코루틴 스코프

플래시🦥 2023. 1. 9.
반응형
setContent {
           Column(
               modifier= Modifier.fillMaxSize(),
               verticalArrangement = Arrangement.Center,
               horizontalAlignment = Alignment.CenterHorizontally
           ){
               TextField(value = "", onValueChange ={} )
               Button(onClick = { }) {
                   Text("Click!")
               }
           }
        }

TextField -> 값 지정 

value ="" : 기본적으로 비어있게 처리

onValueChange={} : 값이 변했을 때의 함수 작성 부분

verticalArrangement = Arrangement.Center  -> 수직중앙정렬

horizontalAlignment = Alignment.CenterHorizontally ->수평 중앙정렬

TextField에 값이 들어가지 않음 => 이유: TextField(value = "", onValueChange ={} 에서 키보드로 입력해도 Value의 값이 변하지 않기 떄문이다.

그래서 

setContent {
    val textvalue = remember {      //텍스트 값을 저장할 변수
        mutableStateOf("")
    }

   Column(
       modifier= Modifier.fillMaxSize(),
       verticalArrangement = Arrangement.Center,
       horizontalAlignment = Alignment.CenterHorizontally
   ){
       TextField(
           value = textvalue.value,
           onValueChange ={
               textvalue.value=it
       } )
       Button(onClick = { }) {
           Text("Click!")
       }
   }
}

텍스트에 값을 저장할 변수 textvalue를 mutablestate로 만들어 주고, 텍스트 필드에 textvalue의 value를 넣어주고, onValueChange에 변하는 값을 textvalue의 value에 대입해주면 된다. 

 

아니면 코틀린의 구조분해 기능을 사용해서 

setContent {
    val (text,setValue) = remember {      //텍스트 값을 저장할 변수
        mutableStateOf("")
    }
   Column(
       modifier= Modifier.fillMaxSize(),
       verticalArrangement = Arrangement.Center,
       horizontalAlignment = Alignment.CenterHorizontally
   ){
       TextField(
           value = text,
           onValueChange = setValue )
       Button(onClick = { }) {
           Text("Click!")
       }
   }
}

이렇게 할 수 도 있다.  달라진 부분은 아래와 같다. 

val (text,setValue) = remember {      //텍스트 값을 저장할 변수
    mutableStateOf("")
}
TextField(
    value = text,
    onValueChange = setValue )

textValue는 text의 생성자 기능을 해줘서, text로 value에 값을 넣어주고 onValueChange= setValue를 넣어 변화를 감지해 줄 수 있다. 

 

버튼을 눌렀을 때 스낵바가 뜨는 기능을 사용하고 싶다면 ui를 만든 코드를 모두 Scaffold로 감싸면 된다.

val scaffoldState = rememberScaffoldState() //최근의 상태를 저장

Scaffold(
    scaffoldState = scaffoldState,
) {

    Column(
        modifier= Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ){
        TextField(
            value = text,
            onValueChange = setValue )
        Button(onClick = {
            scaffoldState.snackbarHostState.showSnackbar("hello $text")
        }) {
            Text("Click!")
        }
    }
}

dㅇ

이렇게 해주면 되는데, 이때 showSnackbar 에서 에러가 발생한다. 

Suspend function 'showSnackbar' should be called only from a coroutine or another suspend function

이런 문구를 확인 할 수 있는데, Suspend function을 사용하기위해서는 coroutine 에서 실행 해야 한다. 

 

**coroutine 을 알고 있어야 한다.

 

우선 간단하게 

val scope = rememberCoroutineScope()

이걸 넣어주고 스낵바를 만들어준 코드를 

scope.launch {
    scaffoldState.snackbarHostState.showSnackbar("hello $text")
}

이렇게 감싸주면 된다. 

 

 

그런데 스낵바를 확인하려면 키보드를 사용자가 일일히 내려야 한다. 

클릭 버튼을 눌렀을 때 자동으로 내려가게 하려면 

val keyboardController =LocalSoftwareKeyboardController.current

이 변수를 추가를 해준다. 아직은 시범적인 기능이기 때문에

@ExperimentalComposeUiApi

도 추가해준다.

그리고 onclick 함수 안에

keyboardController?.hide()

를 추가하여 키보드가 숨겨지도록 한다.

  keyboardController에 물음표는, 값이 null일 수 있기 때문에 안전한 호출을 위해 작성해 준다. 

 


전체 코드

@ExperimentalComposeUiApi
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val (text,setValue) = remember {      //텍스트 값을 저장할 변수
                mutableStateOf("")
            }

            val scaffoldState = rememberScaffoldState() //최근의 상태를 저장
            val scope = rememberCoroutineScope()
            val keyboardController =LocalSoftwareKeyboardController.current

            Scaffold(
                scaffoldState = scaffoldState,
            ) {

                Column(
                    modifier= Modifier.fillMaxSize(),
                    verticalArrangement = Arrangement.Center,
                    horizontalAlignment = Alignment.CenterHorizontally
                ){
                    TextField(
                        value = text,
                        onValueChange = setValue )
                    Button(onClick = {
                        keyboardController?.hide()
                        scope.launch {
                            scaffoldState.snackbarHostState.showSnackbar("hello $text")
                        }
                    }) {
                        Text("Click!")
                    }
                }
            }


        }
    }
}

 

728x90
반응형

댓글