Group Study (2024-2025)/Android

[Android] Android UI 구현 기초

c2c4 2024. 10. 8. 22:28

지정된 강의 1강~5강을 수강하였습니다.

1. Column, Row, Spacer 

Column {
	Text("Hello")
	Text("World")
}

//Column 내의 요소들을 수직으로 배열함


Row{
	Text("Hello")
	Text("World")
}

//Row 내의 요소들을 수평으로 배열

Row{
	Text("Hello")
	Spacer(Modifier.width(16.dp))
	Text("World")
}

//Spacer를 이용해서 요소 사이의 간격을 설정/조절해줄 수 있음

- Column, Row 등의 덩어리에 특성 지정해주기

Column (
	modifier= Modifier //modifier를 이용해 다양한 특성들을 지정해줄 수 있음
		.fillMaxSize() //화면을 꽉 채우기 (text 등 요소들의 크기를 변경하는 게 아님, 다른 특성(배경색 등)이 적용되는 범위 
		.background(color= Color.Blue) //배경 색 지정
		.padding(16.dp), //padding 지정
	
	horizontalAlignment = Alignment.CenterHorizontally, //요소들 가운데 정렬
	verticalArrangement = Arrangement.SpaceBetween //요소들을 각각 위 아래에 붙이고 가운데는 비우기

){
	Text("Hello")
	Text("World")
}

1강 실습

 

2. Composable, Preview

@Composable //Composable이 붙어있다 = Compose이다
fun Greeting(name:String){ //Compose는 함수임에도 불구하고 대문자로 시작
    Text(text="Hello $name!")
}

@Preview(showBackground = true) //preview가 붙어있는 compose는 xml처럼 미리보기 가능
@Composable
fun DefaultPreview(){
    Android_StudyTheme {
        Greeting("Android")
    }
}

//preview 애너테이션이 붙은 애들은 다 미리보기를 볼 수 있다!

2강 실습

 

3. Box

//Box -> 안에 있는 요소들이 다 서로 겹친다 (각각 위치 지정 필요)

Box(
	modifier = Modifier  //modifier를 이용해 다양한 특성 지정 가능
		.background(color=Pink80) //배경색 지정
		.fillMaxWidth() //넓이 max로 지정
		.fillMaxHeight() //높이 max로 지정
		.fillMaxSize(), //넓이, 높이 모두 max로 지정
		
		contentAlignment= Alignment.TopEnd, //상단 우측 정렬, topend 외에도 다양한 위치정렬 선택지들이 있음
	){
	Text("Hello")
	Text("World") //이렇게 그냥 요소를 쭉 쓰면 서로 겹쳐서 보이게 됨
	
	Box( //그래서 요소들도 각각 box로 묶어서 위치 관련 설정을 해줘야 한다
		modifier = Modifier.fillMaxSize(), //부모 box의 size의 max를 가지게 됨
		contentAlignment= Alignment.BottomEnd, //오른쪽 아래 위치하게 됨
	){
		Text("World")
	}
              
}

3강 실습

 

4-1. for문을 이용한 리스트 만들기 (+scroll)

//기존 코틀린의 listview나 recyclerview 와 같은 내용

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            val scrollState = rememberScrollState() //이 스크롤 내용은 무조건 setContent 안에 써줘야 함
            Column(
                modifier = Modifier
                    .background(color= Pink80) 
                    .fillMaxWidth() //이 속성을 추가하지 않으면 글씨가 써지는 부분만 스크롤이 인식됨
                    .verticalScroll(scrollState) //스크롤 추가
                    ){
                for (i in 1..50){
                    Text("글씨 $i") //글씨 1 ~ 글씨 50까지 세로로 쭉 보여지게 된
                }
            }

            }
        }
    }

4강 실습 (1)

 

4-2. LazyColumn

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            val scrollState = rememberScrollState()

            LazyColumn( //위 방식보다 많이 쓰임
                modifier = Modifier
                    .background(color = Pink80)
                    .fillMaxWidth(),
                contentPadding = PaddingValues(16.dp), //사방에 padding 적용
                verticalArrangement = Arrangement.spacedBy(8.dp), //각각의 요소에 간격 적용
            ) {
                item{ //item과 items를 이용해서 요소를 구성할 수 있음
                    Text("Header")
                }
                items(50) { index -> //for문을 이렇게 대체할 수 있다
                    Text("글씨 $index")
                }
                item{
                    Text("Footer")
                }

            }
        }

    }
}

4강 실습 (2)

 

5. Image, Card, 상태 (이미지에 하트 아이콘을 눌렀는지 여부를 저장하고 보여주는 프로그램 작성)

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            var isFavorite by rememberSaveable { 
		            //하트 아이콘을 눌렀는지 여부를 저장하는 변수
		            //가로세로 화면 전환 시에도 상태 유지
                mutableStateOf(false) //처음에는 false로 저장
            }
            ImageCard(
                modifier = Modifier //modifier를 밖에서 지정해줌 (재활용 가능!)
                    .fillMaxWidth(0.5f)                    
                    .padding(16.dp),

                isFavorite=isFavorite, 
            ) {
                favorite ->
                isFavorite = favorite //이 람다식도 매개변수임
            }

        }

    }
}

@Composable
fun ImageCard(
    modifier: Modifier = Modifier,
    isFavorite: Boolean,
    onTabFavorite: (Boolean) -> Unit,
) {
    Card(
        modifier = modifier,
        shape=RoundedCornerShape(8.dp), //코너에 라운드 적용
        elevation = CardDefaults.cardElevation(5.dp), //그림자 효과 적용
    ){
        Box(
            modifier = Modifier.height(200.dp), //높이 지정

            ){
            Image(
                painter = painterResource(id= R.drawable.poster), //이미지 소스
                contentDescription = "poster", //이미지 설명
                contentScale = ContentScale.Crop, //사용 가능한 공간에 맞게 이미지를 가운데를 중심으로 자름
                )
            Box( //포스터 이미지 위에 아이콘을 올리기 위해 box안에 box를 하나 더 올림
                modifier = Modifier.fillMaxSize(), //부모 box의 사이즈 그대로
                contentAlignment = Alignment.TopEnd, //아이콘의 위치 지정
            ){
                IconButton(onClick = { //클릭했을 때 수행할 코드
                    onTabFavorite(!isFavorite) //람다식에 isFavorite 변수의 반대값을 저장함 -> isFavorite의 상태를 바로 바꿔서 저장 가능               }) {
                    Icon(
                        imageVector =
                            if (isFavorite) //만약 true라면
                                Icons.Default.Favorite //채워진 하트 보여주기
                            else //아니라면
                                Icons.Default.FavoriteBorder, //비워진 하트 보여주기

                        contentDescription = "favorite", //아이콘 설명
                        tint = Color.White,

                    )
                }
            }



        }
    }
}

5강 실습