[Jetpack Compose] 1. Compose 기본 사항(2)
📌참고자료:
Jetpack Compose basics
📌참고자료:
padding(bottom = extraPadding.coerceAtLeast(0.dp))
- add @Composable annotation to kotlin function in order to call composable functions inside
- MainActivity의
onCreate
내부 setContent
를 사용해 레이아웃 정의
-> XML 파일 대신, composable function 호출
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BasicsCodelabTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Android")
}
}
}
}
}
- @Preview 애노테이션을 이용하여 미리보기 가능
@Preview(showBackground = true, widthDp = 320, heightDp = 320)
@Preview(
showBackground = true, widthDp = 320, heightDp = 320,
uiMode = UI_MODE_NIGHT_YES,
name = "GreetingPreviewDark"
)
fun GreetingPreview() {
BasicsCodelabTheme {
Greeting(name = "Android")
}
}
LazyColumn
, LazyRow
- a performant lazy list
- renders only the visible items on screen
- doesn't recycle its children like RecyclerView
-> emits new Composables, relatively cheaper than initiating Android Views
- import androidx.compose.foundation.lazy.items
- 리스트 항목의 펼치기/접기 버튼 클릭 시, 항목 하단 padding 값 변경 애니메이션 적용하기
@Composable
fun Greeting(text: String, modifier: Modifier = Modifier) {
var expanded: Boolean by rememberSaveable { mutableStateOf(false) }
val bottomPadding by animateDpAsState(
targetValue = if (expanded) 50.dp else 2.dp,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
)
)
Surface(
modifier = modifier,
color = MaterialTheme.colorScheme.secondary,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = bottomPadding.coerceAtLeast(0.dp))
) {
Text(
modifier = Modifier
.weight(1.8F, true)
.padding(all = 20.dp),
text = text
)
ElevatedButton(
modifier = Modifier
.weight(1.0F, false)
.width(120.dp)
.padding(top = 7.dp, end = 4.dp),
onClick = {expanded = !expanded}
) {
Text(text = if (expanded) "접기" else "펼치기")
}
}
}
}
Scaffold
- a fundamental material design component
- a basic layout for arranging material components in common patterns
Surface
- a central metaphor in Material Design which content sits on
- color, shape, border, shadowElavation, tonalElavation
Layouts
Row
composable function: horizontally arrange items
Column
composable function: vertically arrange items
Box
composable function: put/stack items on top of another
Modifiers
- decorate or augment a composable
- every composable function accepts a modifier as a parameter
Basic layouts in Compose
📌참고자료
- 행의 개수 2개로 고정된 가로 방향 스크롤 그리드 구현
- 항목 사이 여백 설정을 위해
horizontalArrangement
와 verticalArrangement
속성에 Arrangement.spacedBy
사용
- 스크롤 맨 앞&뒤 여백 설정을 위해
contentPadding
속성 사용
@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, Modifier.height(80.dp))
}
}
}
- Slot-based layout
- composable을 매개변수로 받을 때 표현하는 방법:
@Composable () -> Unit
@Composable
fun HomeSection(
@StringRes title: Int,
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Column(modifier) {
Text(stringResource(title))
content()
}
}
- 화면 위아래 스크롤 구현
modifier.verticalScroll(rememberScrollState())
- 화면 위아래 여백 설정을 위해 높이를 가진 Spacer composable 사용
@Composable
fun HomeScreen(modifier: Modifier = Modifier) {
Column(
modifier
.verticalScroll(rememberScrollState())
) {
Spacer(Modifier.height(16.dp))
SearchBar(Modifier.padding(horizontal = 16.dp))
HomeSection(title = R.string.align_your_body) {
AlignYourBodyRow()
}
HomeSection(title = R.string.favorite_collections) {
FavoriteCollectionsGrid()
}
Spacer(Modifier.height(16.dp))
}
}
- Bottom Navigation 레이아웃 구현 (네비게이션 아이템 클릭 구현 X)
@Composable
private fun SootheBottomNavigation(modifier: Modifier = Modifier) {
NavigationBar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
modifier = modifier
) {
NavigationBarItem(
icon = {
Icon(
imageVector = Icons.Default.Spa,
contentDescription = null
)
},
label = {
Text(stringResource(R.string.bottom_navigation_home))
},
selected = true,
onClick = {}
)
NavigationBarItem(
icon = {
Icon(
imageVector = Icons.Default.AccountCircle,
contentDescription = null
)
},
label = {
Text(stringResource(R.string.bottom_navigation_profile))
},
selected = false,
onClick = {}
)
}
}
import androidx.compose.material3.Scaffold
@Composable
fun MySootheAppPortrait() {
MySootheTheme {
Scaffold(
bottomBar = { SootheBottomNavigation() }
) { padding ->
HomeScreen(Modifier.padding(padding))
}
}
}