앞으로 만들어나갈 화면이다.
@Composable
fun SearchBar(
modifier: Modifier = Modifier
) {
TextField(
value = "",
onValueChange = {},
leadingIcon = {
Icon(
imageVector = Icons.Default.Search,
contentDescription = null
)
},
placeholder = {
Text(stringResource(id = R.string.placeholder_search))
},
colors = TextFieldDefaults.colors(
unfocusedContainerColor = MaterialTheme.colorScheme.surface,
focusedContainerColor = MaterialTheme.colorScheme.surface
),
modifier = modifier
.heightIn(min = 56.dp)
.fillMaxWidth()
)
}
TextField를 만들어 입력가능한 창을 만들고, 앞에 아이콘은 leadingIcon을 사용해서 만들어준다. 미리보기는 placeholder로 string값을, 수정자는 가로로 가득 채우고, 새로의 길이는 56dp만큼 만들어준다. colors는 TextField의 상태에 따른 색상을 설정할 수 있다.
focusedContainerColor -> TextField가 포커스 되었을때의 배경색
unfocusedContainerColor -> TextField가 포커스되지 않았을때의 배경색
여기서는 둘다 같은색으로 지정해줬다.

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun SearchBarPreview() {
MySootheThemeTheme {
SearchBar(Modifier.padding(8.dp))
}
}
미리보기의 배경색을 바꿔주고, 수정자에서 padding속성을 넣어서 8dp만큼 떨어지게 만들었다.
@Composable
fun AlignYourBodyElement(
modifier: Modifier = Modifier
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
) {
Image(
painter = painterResource(R.drawable.ab1_inversions),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.size(88.dp)
.clip(CircleShape)
)
Text(text = stringResource(R.string.ab1_inversions))
}
}
이미지는 painter를 사용해서 drawable에 저장한 이미지를 사용하고, 설명은 스킵한다.(contentDescription) contentScale을 사용해서 이미지 조절을 할 수 있고 수정자의 크기를 88dp로 해서 크기를 맞추고 clip을 CircleShape을 해서 원으로 만들어준다.
그리고 Column에 horizontalAlignment설정을 추가해 중앙정렬로 맞춰준다.

@Composable
fun AlignYourBodyElementPreview() {
MySootheThemeTheme {
AlignYourBodyElement(Modifier.padding(8.dp))
}
}
역시나 수정자에 padding을 줬다.
여기서 이 동그란요소를 한번만 사용할게 아니라 여러번 반복해서 사용해야한다. 이러기 위해서 약간의 수정이 필요하다.
@Composable
fun AlignYourBodyElement(
@DrawableRes drawable: Int,
@StringRes text: Int,
modifier: Modifier = Modifier
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
) {
Image(
painter = painterResource(drawable),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.size(88.dp)
.clip(CircleShape)
)
Text(text = stringResource(text),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.paddingFromBaseline(
top = 24.dp, bottom = 8.dp
)
)
}
}
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun AlignYourBodyElementPreview() {
MySootheThemeTheme {
AlignYourBodyElement(
text = R.string.ab1_inversions,
drawable = R.drawable.ab1_inversions,
modifier = Modifier.padding(8.dp)
)
}
}
이미지와 텍스트를 직접 넣는것이 아닌 함수를 불러와줄때 넣어준다.
여기는 위에서 만든 동그란 요소와 비슷하다. 이것 역시 중복해서 사용해야 하니깐 바로 중복가능하게 만들어준다.
@Composable
fun FavoriteCollectionCard(
@DrawableRes drawable: Int,
@StringRes text: Int,
modifier: Modifier = Modifier
) {
Surface(
shape = MaterialTheme.shapes.medium,
color = MaterialTheme.colorScheme.surfaceVariant,
modifier = modifier
) {
Row (
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.width(255.dp)
){
Image(
painter = painterResource(drawable),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.size(80.dp)
)
Text(text = stringResource(text),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = 16.dp)
)
}
}
}
여기 부분은 배경색과 다른 색상이 들어가니깐 Surface 컴포저블을 사용해준다. 그리고 여기서는 모서리를 둥글게 처리해야 하니, shape매개변수를 사용한다.
크기 조절을 위해 Row의 너비를 설정하고 중앙 정렬을 위해 verticalAlignment설정을 진행한다.
나머지는 동그라미를 만들때와 똑같다.
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun FavoriteCollectionCardPreview() {
MySootheThemeTheme {
FavoriteCollectionCard(
text = R.string.fc2_nature_meditations,
drawable = R.drawable.fc2_nature_meditations,
modifier = Modifier.padding(8.dp)
)
}
}

시작전에 총 6가지의 데이터를 넣을건데, 이 데이터들을 매핑시켜준다.
private val alignYourBodyData = listOf(
R.drawable.ab1_inversions to R.string.ab1_inversions,
R.drawable.ab2_quick_yoga to R.string.ab2_quick_yoga,
R.drawable.ab3_stretching to R.string.ab3_stretching,
R.drawable.ab4_tabata to R.string.ab4_tabata,
R.drawable.ab5_hiit to R.string.ab5_hiit,
R.drawable.ab6_pre_natal_yoga to R.string.ab6_pre_natal_yoga
).map { DrawableStringPair(it.first, it.second) }
private val favoriteCollectionsData = listOf(
R.drawable.fc1_short_mantras to R.string.fc1_short_mantras,
R.drawable.fc2_nature_meditations to R.string.fc2_nature_meditations,
R.drawable.fc3_stress_and_anxiety to R.string.fc3_stress_and_anxiety,
R.drawable.fc4_self_massage to R.string.fc4_self_massage,
R.drawable.fc5_overwhelmed to R.string.fc5_overwhelmed,
R.drawable.fc6_nightly_wind_down to R.string.fc6_nightly_wind_down
).map { DrawableStringPair(it.first, it.second) }
private data class DrawableStringPair(
@DrawableRes val drawable: Int,
@StringRes val text: Int
)
저장한 사진과 String값들을 매핑시켜 각 (drawable, string)쌍을 DrawableStringPair객체로 변환해준다.
그리고
@Composable
fun AlignYourBodyRow(
modifier: Modifier = Modifier
) {
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = 16.dp),
modifier = modifier
) {
items(alignYourBodyData) { item ->
AlignYourBodyElement(item.drawable, item.text)
}
}
}
미리 공부한 LazyRow를 이용해서 좌우 스크롤가능한 리스트를 만들어준다.
여기서 horizontalArrangement를 사용해서 각 객체마다 8dp씩 간격을 주고,
contentPadding를 사용해서 객체의 제일앞과 뒷부분에 16dp씩 준다.

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun AlignYourBodyRowPreview() {
MySootheThemeTheme { AlignYourBodyRow() }
}
@Composable
fun FavoriteCollectionsGrid(
modifier: Modifier = Modifier
) {
LazyHorizontalGrid(
rows = GridCells.Fixed(2),
contentPadding = PaddingValues(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = modifier.height(168.dp)
) {
items(favoriteCollectionsData) { item ->
FavoriteCollectionCard(item.drawable, item.text)
}
}
}
rows설정으로 2칸씩 그리드레이아웃 적용시키고
contentPadding사용해서 시작 앞과 뒤 padding적용,
horizontalArrangement사용해서 객체간 앞뒤간격 padding적용,
verticalArrangement사용해서 객체간 위아래 간격 paddign적용,
modifier.height사용해서 높이 168dp적용.

@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
@Composable
fun FavoriteCollectionsGridPreview() {
MySootheThemeTheme { FavoriteCollectionsGrid() }
}
홈화면부터는 다음 포스팅!