
package kr.co.fastcampus.part1.chapter4_13
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kr.co.fastcampus.part1.chapter4_13.ui.theme.StateTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
StateTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background
) {
PyeongToSquareMeter()
}
}
}
}
}
@Composable
fun PyeongToSquareMeter() {
var pyeong by rememberSaveable{ // 저장 공간의 한계가 있기 때문에 remembeSaveable을 사용하는 것은 좋지 않다.
mutableStateOf("23")
}
var squaremeter by rememberSaveable {
mutableStateOf((23 * 3.306).toString())
} // 이러한 자료를 뷰모델에 옮길 수 있다.
// remember는 내부에서 호출하므로 remember와 rememberSaveable만 가장 근본적인 메소드라고 할 수 있고 나머지는 유틸리티다.
// 단계 1: remember를 이용해 상태를 만들고 평 값을 입력하면
// 제곱미터가 출력되도록 화면을 구성하시오.
// 평을 제곱미터로 바꾸기 위해서는 3.306을 곱하면 됩니다.
// Column(modifier = Modifier.padding(16.dp)) {
// OutlinedTextField(
// value = pyeong,
// onValueChange = {
// if (it.isEmpty()) {
// pyeong = ""
// squaremeter = ""
// return@OutlinedTextField
// }
// val numericValue = it.toFloatOrNull() ?: return@OutlinedTextField // 강제 종료
// pyeong = it
// squaremeter = (numericValue * 3.306).toString()
// }, label = {
// Text("평")
// }
// )
// OutlinedTextField(
// value = squaremeter,
// onValueChange = {},
// label = {
// Text("제곱미터")
// }
// )
// } // 현재 이 상태가 전달되는 방식은 좋지 못한 방식이다.
// 그래서 상태가 전달되는 범위를 좁히기 위해서 상태를 윗단으로 끌어올리는 것을 StateHoisting이라고 한다.
// 단계 2: `Composable` 함수를 만들고 `Column`의 항목들을 옮기세요.
// 단 상태는 옮기지 말아야 합니다.
// 파라미터는 아래와 같이 구성합니다.
// `pyeong: String, squareMeter: String, onPyeongChange: (String) -> Unit`
PyeongToSquareMeterStateless(pyeong, squaremeter){
if (it.isEmpty()) {
pyeong = ""
squaremeter = ""
return@PyeongToSquareMeterStateless
}
val numericValue = it.toFloatOrNull() ?: return@PyeongToSquareMeterStateless // 강제 종료
pyeong = it
squaremeter = (numericValue * 3.306).toString()
}
} // 하나의 컴포저블에만 상태를 넣을 수 있따.
@Composable // 다른 컴포저블은 샅애를 가지지 않게 할 수 있다.
fun PyeongToSquareMeterStateless(
pyeong: String,
squareMeter: String,
onPyeongChange: (String) -> Unit // 이 것을 통해 상태를 바꿈
) { // state를 바꿀 책임을 위에 올리고 여기는 상태를 가지고 있지 않기 때문에 상태를 바꾸지 않을 것이다.
Column(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = pyeong,
onValueChange = onPyeongChange,
label = {
Text("평")
}
)
OutlinedTextField(
value = squareMeter,
onValueChange = {},
label = {
Text("제곱미터")
}
)
}
} // 이렇게 하면 테스트하기 쉬워 진다.
@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
StateTheme {
PyeongToSquareMeter()
}
}