@Composable
public fun Card(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = CardDefaults.shape,
colors: CardColors = CardDefaults.cardColors(),
elevation: CardElevation = CardDefaults.cardElevation(),
border: BorderStroke? = null,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable() (ColumnScope.() -> Unit)
): Unit
카드 형태의 UI 요소를 생성할 때 사용
이 함수는 여러 매개변수를 통해 카드의 모양, 색상, 동작 등을 커스터마이징할 수 있다.
enabled: 카드를 클릭할 수 있는지 여부를 결정.
shape: 카드의 모양을 정의하는 Shape 객체. 기본값은 CardDefaults.shape
border: 카드의 테두리를 정의하는 BorderStroke 객체. 기본값은 null
interactionSource
사용자와의 상호작용을 추적하는 MutableInteractionSource 객체
기본값은 remember { MutableInteractionSource() }
다음 매개변수를 통해 정렬할 수 있다.
@Composable
@ExperimentalLayoutApi
public inline fun FlowRow(
modifier: Modifier = Modifier,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
maxItemsInEachRow: Int = Int.MAX_VALUE,
content: @Composable() (FlowRowScope.() -> Unit)
): Unit
수평으로 아이템을 배치하고, 공간이 부족하면 자동으로 다음 줄로 넘어가서 배치하는 레이아웃
maxItemsInEachRow : 한 줄에
@Composable
public fun ListItem(
headlineContent: @Composable () -> Unit,
modifier: Modifier = Modifier,
overlineContent: @Composable() (() -> Unit)? = null,
supportingContent: @Composable() (() -> Unit)? = null,
leadingContent: @Composable() (() -> Unit)? = null,
trailingContent: @Composable() (() -> Unit)? = null,
colors: ListItemColors = ListItemDefaults.colors(),
tonalElevation: Dp = ListItemDefaults.Elevation,
shadowElevation: Dp = ListItemDefaults.Elevation
): Unit
ListItem은 리스트 항목을 쉽게 구성할 수 있도록 제공.
이 함수는 여러 슬롯을 사용하여 리스트 항목의 다양한 부분을 정의할 수 있다.
이를 통해 각 리스트 항목의 헤드라인, 서포팅 텍스트, 선행 및 후행 콘텐츠 등을
쉽게 구성할 수 있다
@Composable
public fun LazyVerticalStaggeredGrid(
columns: StaggeredGridCells,
modifier: Modifier = Modifier,
state: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
verticalItemSpacing: Dp = 0.dp,
horizontalArrangement: Arrangement.Horizontal = Arrangement.spacedBy(0.dp),
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled: Boolean = true,
content: LazyStaggeredGridScope.() -> Unit
): Unit
스크롤 가능한 수직 스태거드 그리드(아이템들이 비대칭적으로 배치되는 그리드)를
만들기 위한 함수
스태거드 그리드는, 아이템의 크기가 일정하지 않거나 다양한 경우에 유용
columns: StaggeredGridCells
그리드의 열 수를 정의합니다.
StaggeredGridCells.Fixed와 StaggeredGridCells.Adaptive로 설정
📌
StaggeredGridCells.Fixed
StaggeredGridCells.Adaptive
state: LazyStaggeredGridState
그리드의 스크롤 상태를 관리하는 상태 객체입니다. 기본값은 rememberLazyStaggeredGridState()입니다.
verticalItemSpacing: Dp
각 아이템 사이의 수직 간격을 설정. 기본값은 0.dp
horizontalArrangement: Arrangement.Horizontal
각 열 사이의 수평 간격을 설정. 기본값은 Arrangement.spacedBy(0.dp)
flingBehavior: FlingBehavior
플링(fling) 동작을 정의하는 객체.
기본값은 ScrollableDefaults.flingBehavior()
📌 플링(fling) 동작
사용자 인터페이스(UI)에서 스크롤과 관련된 제스처 중 하나로, 사용자가 스크린을 빠르게 스와이프한 후, 그 스와이프 동작에 따른 관성으로 인해 콘텐츠가 자동으로 스크롤되는 동작을 의미. 플링은 일반적으로 스크롤을 멈추지 않고 자연스럽게 계속 움직이게 하여 사용자가 더 부드럽고 직관적인 경험을 할 수 있도록 한다
Row | Column |
---|---|
LazyColumn : 화면에 보이는 항목만 렌더링하므로 항목이 많은 목록을 렌더링할 때 성능이 향상 된다.
📌참고: LazyColumn은 RecyclerView와 달리 자식 요소를 재활용하지 않는다.
LazyColumn은 스크롤하는 동안 새로운 Composable을 생성하며, Android View를 인스턴스화하는 것에 비해 Composable을 생성하는 것이 더 효율적이기 때문이다.
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
...
@Composable
private fun Greetings(
modifier: Modifier = Modifier,
names: List<String> = List(1000) { "$it" }
) {
LazyColumn(modifier = modifier.padding(vertical = 4.dp)) {
items(items = names) { name ->
Greeting(name = name)
}
}
}
modifier: Modifier,
state: LazyListState,
contentPadding: PaddingValues(all:Dp or horizontal: Dp, vertical: Dp)
// modifier로 패딩을 줄 경우 콘텐츠를 자르게 되는 현상이 발생하기 때문에 contentPadding에 패딩을 줘서 이런 현상을 막아주도록 한다.
reverseLayout: Boolean,
horizontalArrangement: Arrangement.Horizontal,
// Arrangement.spacedBy(dp)를 사용하여 각 하위 컴포저블 사이에 고정된 공간을 추가할 수 있다.
verticalAlignment: Alignment.Vertical,
flingBehavior: FlingBehavior,
userScrollEnabled: Boolean,
content: LazyListScope.() -> Unit
rows: GridCells,
// GridCells.(Fixed, FixedSize, Adaptive)
1. Fixed(count:Int) : 고정된 열 수를 가진 그리드 생성
2. FixedSize(size:Dp) : ?
3. Adaptive(minSize:Dp) : 최소 크기를 가진 적응형 그리드 생성 각 행은 최소 크기를 기준으로 가능한 많은 아이템을 포함하며, 화면 크기에 따라 열의 수가 조정된다.
modifier: Modifier,
state: LazyGridState,
contentPadding: PaddingValues,
reverseLayout: Boolean,
horizontalArrangement: Arrangement.Horizontal, // 수평 간격
verticalArrangement: Arrangement.Vertical, // 수직 간격
flingBehavior: FlingBehavior,
userScrollEnabled: Boolean,
content: LazyGridScope.() -> Unit
Compose Material 라이브러리의 구성요소이다. Material Design 패턴을 따르며, 앱의 테마를 변경하여 조정할 수 있다.
@OptIn(markerClass = {androidx.compose.material3.ExperimentalMaterial3Api::class})
@Composable
public fun TextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
label: @Composable() (() -> Unit)? = null,
placeholder: @Composable() (() -> Unit)? = null,
leadingIcon: @Composable() (() -> Unit)? = null,
trailingIcon: @Composable() (() -> Unit)? = null,
prefix: @Composable() (() -> Unit)? = null,
suffix: @Composable() (() -> Unit)? = null,
supportingText: @Composable() (() -> Unit)? = null,
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
minLines: Int = 1,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = TextFieldDefaults.shape,
colors: TextFieldColors = TextFieldDefaults.colors()
): Unit
prefix: 텍스트 필드의 앞에 표시
suffix: 텍스트 필드의 뒤에 표시
supportingText: 텍스트 필드의 아래쪽에 표시되는 지원 텍스트를 나타낸다
visualTransformation
@Composable
public fun BasicTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
minLines: Int = 1,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
cursorBrush: Brush = SolidColor(Color.Black),
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit = @Composable { innerTextField -> innerTextField() }
): Unit
onTextLayout
decorationBox
checked: Boolean,
onCheckedChange: ((Boolean) -> Unit)?,
modifier: Modifier,
enabled: Boolean,
colors: CheckboxColors,
interactionSource: MutableInteractionSource
컴포저블 내에서 하나 이상의 NavigationBarItem
요소를 추가하면 Material 라이브러리에 의해 자동으로 스타일이 지정된다.
modifier: Modifier,
containerColor: Color, // 하단 탐색의 배경색 설정
contentColor: Color,
tonalElevation: Dp,
windowInsets: WindowInsets,
content: @Composable() (RowScope.() -> Unit)
selected: Boolean, // 초기 클릭 상태 지정
onClick: () -> Unit,
icon: @Composable () -> Unit, // 아이콘 설정
modifier: Modifier,
enabled: Boolean,
label: @Composable() (() -> Unit)?,
alwaysShowLabel: Boolean,
colors: NavigationBarItemColors,
interactionSource: MutableInteractionSource
modifier: Modifier,
containerColor: Color,
contentColor: Color,
header: @Composable() (ColumnScope.() -> Unit)?,
windowInsets: WindowInsets,
content: @Composable() (ColumnScope.() -> Unit)
selected: Boolean,
onClick: () -> Unit,
icon: @Composable () -> Unit,
modifier: Modifier,
enabled: Boolean,
label: @Composable() (() -> Unit)?,
alwaysShowLabel: Boolean,
colors: NavigationRailItemColors,
interactionSource: MutableInteractionSource
Material Design을 구현하는 앱을 위한 최상위 수준 컴포저블을 제공한다. 여기에는 다양한 Material 개념의 슬롯이 포함되어 있다.
modifier: Modifier,
topBar: @Composable () -> Unit,
bottomBar: @Composable () -> Unit,
snackbarHost: @Composable () -> Unit,
floatingActionButton: @Composable () -> Unit,
floatingActionButtonPosition: FabPosition,
containerColor: Color,
contentColor: Color,
contentWindowInsets: WindowInsets,
content: @Composable (PaddingValues) -> Unit
public fun <T : View> AndroidView(
factory: (Context) -> T,
modifier: Modifier,
update: (T) -> Unit
): Unit
AndroidView
를 사용하면 factory
에서 View
를 생성할 수 있게 해준다. 또한 뷰가 확장되었을 때와 이후 리컴포지션에서 호출되는 update
를 제공한다.
📌 AndroidView를 사용하면 프로그래미틱 방식으로 뷰를 만들 수 있다. XML 파일에서 뷰를 확장하려는 경우 androidx.compose.ui:ui-viewbinding
라이브러리의 AndroidViewBinding
API와 함께 ViewBinding을 사용하면 된다.
@Composable
@ExperimentalMaterial3Api
@ComposableInferredTarget
public fun SwipeToDismiss(
state: DismissState,
background: @Composable() (RowScope.() -> Unit),
dismissContent: @Composable() (RowScope.() -> Unit),
modifier: Modifier,
directions: Set<DismissDirection>
): Unit
Material 3 라이브러리의 일부로 제공되는 Compose 함수
주로, 사용자가 화면에서 스와이프하여 아이템을 제거하는 기능을 구현하는 데 사용
아이템을 제거하는 대신 일종의 "액션"을 수행하는 데에 활용할 수 있다.
state: DismissState 타입으로, 스와이프 동작의 상태를 제어
background: 스와이프된 아이템의 배경을 그리기 위한 Composable 블록
dismissContent: 스와이프된 아이템을 표시하는 Composable 블록
modifier: Modifier를 통해 SwipeToDismiss의 외형을 조정할 수 있다.
directions: 스와이프가 허용되는 방향을 설정합니다. DismissDirection.StartToEnd 또는 DismissDirection.EndToStart 중 하나를 선택할 수 있다.
SwipeToDismiss(
state = dismissState,
modifier = modifier
.fillMaxWidth()
.height(100.dp),
dismissContent = { // content
},
background = { // dismiss content
val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
val color by animateColorAsState(
when (dismissState.targetValue) {
DismissValue.Default -> backgroundColor.copy(alpha = 0.5f) // dismissThresholds 만족 안한 상태
DismissValue.DismissedToEnd -> Color.Green.copy(alpha = 0.4f) // -> 방향 스와이프 (수정)
DismissValue.DismissedToStart -> Color.Red.copy(alpha = 0.5f) // <- 방향 스와이프 (삭제)
}, label = ""
)
val icon = when (dismissState.targetValue) {
DismissValue.Default -> Icons.Default.Circle
DismissValue.DismissedToEnd -> Icons.Default.Edit
DismissValue.DismissedToStart -> Icons.Default.Delete
}
val scale by animateFloatAsState(
when (dismissState.targetValue == DismissValue.Default) {
true -> 0.8f
else -> 1.5f
}, label = ""
)
val alignment = when (direction) {
DismissDirection.EndToStart -> Alignment.CenterEnd
DismissDirection.StartToEnd -> Alignment.CenterStart
}
Box(
modifier = Modifier
.fillMaxSize()
.background(color)
.padding(horizontal = 30.dp),
contentAlignment = alignment
) {
Icon(
modifier = Modifier.scale(scale),
imageVector = icon,
contentDescription = null
)
}
}
)
@ExperimentalMaterial3Api
@Composable
@ComposableInferredTarget
public fun TopAppBar(
title: @Composable () -> Unit,
modifier: Modifier,
navigationIcon: @Composable () -> Unit,
actions: @Composable() (RowScope.() -> Unit),
windowInsets: WindowInsets,
colors: TopAppBarColors,
scrollBehavior: TopAppBarScrollBehavior?
): Unit
title: @Composable () -> Unit 타입, 제목을 정의
navigationIcon: @Composable () -> Unit 타입, 네비게이션 아이콘을 정의
actions: @Composable() (RowScope.() -> Unit) 타입, 추가적인 작업을 위한 아이콘 등을 정의
windowInsets: WindowInsets 타입, 시스템 창(window insets)을 어떻게 처리할지 정의
colors: TopAppBarColors 타입, 색상을 정의
scrollBehavior: TopAppBarScrollBehavior 타입, 스크롤 동작을 정의
💡TopAppBarDefaults.enterAlwaysScrollBehavior() 등등 함수들이 있다.
스크롤 동작을 설정하는 함수
EnterAlways (기본값): 사용자가 아래로 스크롤할 때 앱 바가 위로 숨겨진다
Material Design 라이브러리에서 제공되는 컴포저블
@ExperimentalMaterial3Api
@Composable
@ComposableInferredTarget
public fun CenterAlignedTopAppBar(
title: @Composable () -> Unit,
modifier: Modifier = COMPILED_CODE,
navigationIcon: @Composable () -> Unit = COMPILED_CODE,
actions: @Composable() (RowScope.() -> Unit) = COMPILED_CODE,
windowInsets: WindowInsets = COMPILED_CODE,
colors: TopAppBarColors = COMPILED_CODE,
scrollBehavior: TopAppBarScrollBehavior? = COMPILED_CODE
): Unit
NavHost는 네비게이션을 관리하기 위한 중요한 요소 중 하나
@Composable
public fun NavHost(
navController: NavHostController,
startDestination: String,
modifier: Modifier = COMPILED_CODE,
route: String? = COMPILED_CODE,
builder: NavGraphBuilder.() -> Unit
): Unit
navController: NavController 타입, 현재 앱의 네비게이션 상태를 나타낸다
startDestination: String 타입, 앱이 시작될 때 첫 번째 목적지를 나타냄
route: String 타입, NavHost 자체의 경로를 정의
builder: NavGraphBuilder.() -> Unit 타입, NavHost 안에서 목적지를 정의
예시
@Composable
fun MyApp() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "screen1") {
composable(route = "screen1") {
Screen1(navController = navController)
}
composable(route = "screen2") {
Screen2()
}
}
}
NavController와 startDestination이 필요
NavController는 현재 앱의 상태를 나타내며, 각 화면 간의 전환을 처리rememberNavController()을 사용하여 NavController를 생성하고 기억
startDestination은 앱이 시작될 때 처음 표시되는 화면을 지정
composable 함수는 NavHost의 두 번째 매개변수로 전달되는 builder 블록 안에서 사용
route 정의 예시
interface NavigationDestination {
//Unique name to define the path for a composable
val route: String
//String resource id to that contains title to be displayed for the
val titleRes: Int
}
object HomeDestination : NavigationDestination {
override val route = "home"
override val titleRes = R.string.app_name
}
NavHostController는 앱의 네비게이션을 관리하고 화면 간의 전환을 처리하는 데 사용
목적지로 이동: navigate() 메서드를 사용, 다른 화면으로 이동
뒤로가기: popBackStack(), navigateUp() 메서드를 사용, 현재 화면을 빠져나와 이전 화면으로 돌아갈 수 있다
📌 popBackStack(), navigateUp() 차이점
동작 방식
navigateUp(): 이전 화면이 없으면 앱을 닫는다
popBackStack(): 이전 화면이 스택에 없으면 앱을 닫지 않고 현재 화면만 닫는다
스택 조작
navigateUp(): 네비게이션 스택에서 현재 목적지를 제거하지 않고 이동
앱 내부에서의 네비게이션 스택 관리: NavHostController는 네비게이션 스택을 관리
Safe Args와 함께 사용: Navigation Compose에서는 Safe Args를 사용하여 목적지로 데이터를 전달할 수 있다
SideEffect는 상태의 변경이나 다른 효과를 일으킬 수 있는 코드 블록을 실행하는 데 사용
📌 사용하는 이유
Composable 함수는 렌더링 시 매번 호출되기 때문에 Composable 함수 내에 상태 변경 로직을 넣으면 렌더링마다 상태가 변경되어 원하지 않는 결과를 초래할 수 있다
SideEffect를 사용하면 Composable 함수의 주된 기능과는 별개로 상태 변경 로직을 분리하여 사이드 이펙트를 발생시킬 수 있다
SideEffect 안에서 상태 변경이 일어나면, Composable 함수가 다시 호출되지 않고 이펙트만 발생
@Composable
public fun SideEffect(
effect: () -> Unit
): Unit
effect: () -> Unit 타입, 상태의 변경이나 다른 효과를 일으킬 수 있는 코드 블록을 받는다
@OptIn(markerClass = {androidx. compose. material. ExperimentalMaterialApi::class})
@Composable
public fun BackdropScaffold(
appBar: @Composable () -> Unit,
backLayerContent: @Composable () -> Unit,
frontLayerContent: @Composable () -> Unit,
modifier: Modifier = Modifier,
// frontLayerContent가 닫혀있는지, 열려있는지 결정 BackdopValue.Revealed / BackdopValue.Concealed
scaffoldState: BackdropScaffoldState = rememberBackdropScaffoldState(Concealed),
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
// 백드롭을 열고 닫는 기능을 사용할지 여부
gesturesEnabled: Boolean = true,
// frontLayer를 올렸을 때, 보이는 backLayer의 최소 높이를 지정. 기본값은 PeekHeight(56.dp)
peekHeight: Dp = BackdropScaffoldDefaults.PeekHeight,
// frontLayer의 헤더 높이 설정. 기본값 HeaderHeight(48.dp)
headerHeight: Dp = BackdropScaffoldDefaults.HeaderHeight,
// 기본값: appBar가 항상보임. false: frontLayer가 끝까지 올라가야 appBar 보임
persistentAppBar: Boolean = true,
// 기본값(true): frontLayer가 backLayer밑으로 고정된 위치를 가짐.
// false: frontLayer가 고정된 위치가 아닌 끝까지 올라가거나 헤더만 보이게 됨
stickyFrontLayer: Boolean = true,
backLayerBackgroundColor: Color = MaterialTheme.colors. primary,
backLayerContentColor: Color = contentColorFor(backLayerBackgroundColor),
frontLayerShape: Shape = BackdropScaffoldDefaults.frontLayerShape,
frontLayerElevation: Dp = BackdropScaffoldDefaults.FrontLayerElevation,
frontLayerBackgroundColor: Color = MaterialTheme.colors. surface,
frontLayerContentColor: Color = contentColorFor(frontLayerBackgroundColor),
// frontLayer가 완전히 열리지 않았을 때 색상 기본값(0.6f)
frontLayerScrimColor: Color = BackdropScaffoldDefaults.frontLayerScrimColor
): Unit
Backdrop 레이아웃을 구현하는 데 사용