본문 바로가기

TIL

TIL 68일차 - 최종프로젝트

Compose를 이용해 로그인 화면의 UI를 만들어 보았다.

class LoginActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeTestTheme {
                Surface (
                    modifier = Modifier.fillMaxSize()
                ) {
                    LoginScreen()
                }
            }
        }
    }
}

@Composable
fun LoginScreen() {

    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }

    Column (
        modifier = Modifier
            .fillMaxSize()
            .background(Color(0xFFFFEDED)),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Text (
            text = "환영합니다",
            fontSize = 36.sp,
            fontWeight = FontWeight.Bold,
            color = Color.Black
        )

        Spacer (modifier = Modifier.height(5.dp))

        Text (
            text = "로그인 후 이용해 주세요",
            fontSize = 20.sp,
            color = Color.Black
        )

        Spacer (modifier = Modifier.height(16.dp))

        OutlinedTextField (
            value = email,
            onValueChange = { email = it },
            label = { Text (text = "이메일", color = Color.Gray) },
            colors = TextFieldDefaults.colors(
                focusedIndicatorColor = Color.Black,
                unfocusedIndicatorColor = Color.Black,
                unfocusedContainerColor = Color.White,
                focusedContainerColor = Color.White,
                focusedTextColor = Color.Black,
                unfocusedTextColor = Color.Black
            )
        )

        Spacer(modifier = Modifier.height(16.dp))

        OutlinedTextField (
            value = password,
            onValueChange = { password = it },
            label = { Text (text = "비밀번호", color = Color.Gray) },
            visualTransformation = PasswordVisualTransformation(),
            colors = TextFieldDefaults.colors(
                focusedIndicatorColor = Color.Black,
                unfocusedIndicatorColor = Color.Black,
                unfocusedContainerColor = Color.White,
                focusedContainerColor = Color.White,
                focusedTextColor = Color.Black,
                unfocusedTextColor = Color.Black
            )
        )

        Row (
            modifier = Modifier
                .fillMaxWidth()
                .padding(50.dp),
            horizontalArrangement = Arrangement.SpaceEvenly,
            verticalAlignment = Alignment.CenterVertically

        ) {
            Button (
                modifier = Modifier
                    .width(100.dp)
                    .height(40.dp),
                onClick = { Log.d("로그인", "Email : $email , password : $password") },
                shape = RoundedCornerShape(12.dp),
                border = BorderStroke(0.5.dp, Color.Black),
                elevation = ButtonDefaults.buttonElevation(
                    defaultElevation = 2.dp
                ),
                colors = ButtonDefaults.buttonColors(
                    containerColor = Color(0xFF59C1BD)
                )
            ) {
                Text (text = "로그인", color = Color.White)
            }

            Spacer (modifier = Modifier.width(30.dp))

            Button (
                modifier = Modifier
                    .width(100.dp)
                    .height(40.dp),
                onClick = { /*TODO*/ },
                shape = RoundedCornerShape(12.dp),
                border = BorderStroke(0.5.dp, Color.Black),
                elevation = ButtonDefaults.buttonElevation(
                    defaultElevation = 2.dp
                ),
                colors = ButtonDefaults.buttonColors(
                    containerColor = Color(0xFF59C1BD)
                )
            ) {
                Text (text = "회원가입", color = Color.White)
            }
        }

        TextButton (
            onClick = { /*TODO*/ },
            border = BorderStroke(0.5.dp, Color.Black),
            shape = RoundedCornerShape(0.dp),
        ) {
            Text (text = "비밀번호가 기억이 안나요", color = Color.Black)
        }

        Row (
            modifier = Modifier
                .fillMaxWidth()
                .padding(40.dp),
            horizontalArrangement = Arrangement.SpaceEvenly,
            ) {
            Image (
                painter = painterResource (id = R.drawable.ic_launcher_background),
                contentDescription = "Icon",
                modifier = Modifier
                    .size(60.dp)
                    .clickable { /*TODO*/ }
            )

            Image (
                painter = painterResource(id = R.drawable.ic_launcher_background),
                contentDescription = "Icon",
                modifier = Modifier
                    .size(60.dp)
                    .clickable { /*TODO*/ }
            )

            Image(painter = painterResource(id = R.drawable.ic_launcher_background),
                contentDescription = "Icon",
                modifier = Modifier
                    .size(60.dp)
                    .clickable { /*TODO*/ }
            )
        }
    }
}

@Preview(showBackground = true)
@Composable
fun LoginScreenPreview() {
    LoginScreen()
}

 

주의깊게 봐야 할 부분 몇가지만 보도록 하자.

@Composable
fun LoginScreen() {

    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }

 

remember와 mutableStateOf를 이용해 이메일과 비밀번호의 입력값을 저장한다. 레이아웃 코드의 editText와 동일한 기능을 하기 위함이다.

Compose는 TextField의 상태가 바뀔 때마다 Recompose라는 것을 하기 때문에 remember를 사용해 별도로 값을 저장할 필요가 있다.

        OutlinedTextField (
            value = email,
            onValueChange = { email = it },
            label = { Text (text = "이메일", color = Color.Gray) },
            colors = TextFieldDefaults.colors(
                focusedIndicatorColor = Color.Black,
                unfocusedIndicatorColor = Color.Black,
                unfocusedContainerColor = Color.White,
                focusedContainerColor = Color.White,
                focusedTextColor = Color.Black,
                unfocusedTextColor = Color.Black
            )
        )

 

이후 value, onValueChange를 이용해 저장된 값을 사용하는 모습이다. 비밀번호도 마찬가지이다.

 

    Column (
        modifier = Modifier
            .fillMaxSize()
            .background(Color(0xFFFFEDED)),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    )

 

verticalArrangement와 horizontalAlignment는 Compose를 정렬할 때 사용되는 중요한 함수이다. Center값을 주어 중앙 정렬하도록 구현했다.

두 함수가 없으면 위와 같이 정렬되지 않고 쌓이기만 한다

Button (
                modifier = Modifier
                    .width(100.dp)
                    .height(40.dp),
                onClick = { Log.d("로그인", "Email : $email , password : $password") },
                shape = RoundedCornerShape(12.dp),
                border = BorderStroke(0.5.dp, Color.Black),
                elevation = ButtonDefaults.buttonElevation(
                    defaultElevation = 2.dp
                ),
                colors = ButtonDefaults.buttonColors(
                    containerColor = Color(0xFF59C1BD)
                )
            ) {
                Text (text = "로그인", color = Color.White)
            }

 

버튼에 사용된 여러 값들이다. 직관적으로 해석할 수 있는 쉬운 코드이다. colors를 이용해 버튼의 여러 상태(눌렸을 때, 기본 상태 등..)에 대한 색을 지정할 수 있다.

 

            Image (
                painter = painterResource (id = R.drawable.ic_launcher_background),
                contentDescription = "Icon",
                modifier = Modifier
                    .size(60.dp)
                    .clickable { /*TODO*/ }
            )

 

painter를 이용해 기존처럼 drawable 등에서 이미지 파일을 불러올 수 있다.

'TIL' 카테고리의 다른 글

TIL 70일차 - 최종프로젝트  (0) 2024.06.28
TIL 69일차 - 최종프로젝트  (0) 2024.06.27
TIL 67일차 - 최종프로젝트  (0) 2024.06.25
TIL 66일차 - 최종프로젝트  (0) 2024.06.24
TIL 65일차 - 최종프로젝트  (0) 2024.06.21