이번 포스팅은 은근 사용 하는 컴포즈의 드롭다운 만드는 법을 작성해 보겠다.
기존 XML에서는 어댑터도 만들고 리스너로 이벤트 처리를 해서 코드가 분산되어 흐름을 한눈에 보기 힘들었다.
반면 컴포즈에서는 단일 함수 내에서 완전한 구현이 가능하기 때문에 많이 편리해졌다.
그럼 이제 사용법을 알아보자!
# DropdownMenu
@Composable
fun DropdownMenu(
expanded: Boolean,
onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
offset: DpOffset = DpOffset(0.dp, 0.dp),
scrollState: ScrollState = rememberScrollState(),
properties: PopupProperties = PopupProperties(focusable = true),
content: @Composable ColumnScope.() -> Unit
)
해당 코드는 DropdownMenu의 내부 코드이다. 각각 매개변수에 대한 설명을 하자면 아래와 같다.
- expanded : 드롭다운 메뉴가 표시될지 숨겨질지를 결정하는 값 (ture - 표시, false - 숨김)
- onDismissRequest - 드롭다운 외부를 클릭하거나 뒤로 가기 버튼을 눌렀을 때 호출되는 콜백 함수
- modifier - 드롭다운 메뉴의 대한 Modifier
- offset - 드롭다운 메뉴가 표시될 위치의 오프셋을 지정하는 값
- scrollState - 메뉴 항목이 많아 스크롤이 필요할 때 사용되는 스크롤 상태 객체
- properties - 드롭다운의 동작 (포커스 가능 여부 등)을 정의하는 속성
- content - 드롭다운 메뉴 내부에 표시될 컴포저블 콘텐츠를 정의하는 람다 함수 기본은 ColumnScope이다.
# 예제
만약 과일 리스트를 드롭다운메뉴로 보여줘야 하는 일이 있다는 예제를 통해 정확한 사용법을 알아보자!
간단하게는 3단계로 나타낼 수 있다.
## expanded 상태를 위한 remember State변수 선언
var isDropBoxShow by remember { mutableStateOf(false) }
우선 expanded 상태가 변경이 될 때마다 저장 후 리컴포지션이 일어야 나야 하기 때문에 remember와 mutableState를 사용해 Boolean 변수를 선언해준다.
## expanded 상태 변화를 위한 버튼 컴포저블 생성
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { isDropBoxShow = true }
) {
Text("과일 리스트 보여주기")
}
드롭다운메뉴를 보여주기 위해서는 위에서 살펴본 DropdownMenu 매개변수의 expanded를 true를 전달해줘야 한다.
해당 버튼은 클릭 시 만들어준 변수의 값을 ture로 바꿔주는 역할을 한다.
## DropdownMenu을 보여주는 DropdownMenu정의
DropdownMenu(
modifier = Modifier.fillMaxWidth(),
expanded = isDropBoxShow,
onDismissRequest = { isDropBoxShow = false },
content = {
// DropdownMenu의 MenuItem
Text(
modifier = Modifier.fillMaxWidth(),
text = "사과"
)
Text(
modifier = Modifier.fillMaxWidth(),
text = "바나나"
)
Text(
modifier = Modifier.fillMaxWidth(),
text = "딸기"
)
}
)
해당 드롭박스메뉴 매개변수에 expanded 값은 위에서 만들어준 isDropBoxShow를 넣어주고 onDismissRequest가 발생하면 isDropBoxShow에 false로 바꿔 줌으로써 드롭박스메뉴가 숨겨지게 된다.
content안에는 컴포저블 함수 모두 가능하니 위 예제처럼 커스텀도 가능하다!
아래는 전체 코드와 예제 영상이다.
fun DropBoxTest() {
// expanded 상태를 위한 remember 변수 선언
var isDropBoxShow by remember { mutableStateOf(false) }
Box {
// expanded 상태 변화를 위한 버튼 생성
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { isDropBoxShow = true }
) {
Text("과일 리스트 보여주기")
}
// expanded 상태일 때 DropdownMenu을 보여주는 DropdownMenu
DropdownMenu(
modifier = Modifier.fillMaxWidth(),
expanded = isDropBoxShow,
onDismissRequest = { isDropBoxShow = false },
content = {
// DropdownMenu의 MenuItem
Text(
modifier = Modifier.fillMaxWidth(),
text = "사과"
)
Text(
modifier = Modifier.fillMaxWidth(),
text = "바나나"
)
Text(
modifier = Modifier.fillMaxWidth(),
text = "딸기"
)
}
)
}
}
❗️ 여기서 하나의 팁을 주자면 DropDownMenuItem을 이용하면 DropDownMenu에 들어갈 아이템들을 쉽게 만들 수 있다.
## DropDownMenuItem를 이용한 DropdownMenu
DropDownMenuItem은 Material package에서 미리 디자인된 컴포저블이다!
따라서 DropDownMenuItem 컴포저블을 사용하면 쉽게 DropdownMenu에 들어갈 아이템들을 만들 수 있다는 장점이 있다.
사용법을 알기 전에 우선 내부 코드를 살펴보자!
@Composable
fun DropdownMenuItem(
text: @Composable () -> Unit,
onClick: () -> Unit,
modifier: Modifier = Modifier,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
enabled: Boolean = true,
colors: MenuItemColors = MenuDefaults.itemColors(),
contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
)
- text : 메뉴 항목에 표시될 텍스트 내용을 정의하는 컴포저블 함수
- onClick : 메뉴 항목을 클릭했을 때 실행될 콜백 함수
- modifier : 메뉴 항목의 대한 modifier
- leadingIcon : 텍스트 앞에 표시될 아이콘을 정의할 수 있는 컴포저블 함수
- trailingIcon : 텍스트 뒤에 표시될 아이콘을 정의 할 수 있는 컴포저블 함수
- enabled : 항목이 활성화 상태인지 여부를 결정 (false일 경우 클릭 불가)
- colors : 메뉴 항목에 배경생, 콘텐츠 색상 등을 결정하는 객체
- contentPadding : 메뉴 항목 내부 콘텐츠의 패딩 값을 지정
- interactionSource : 클릭 등 상호작용 상태를 처리하는 객체
이제 내부 코드를 알아봤으니 위 예제와 동일하게 과일 리스트를 드롭다운메뉴로 보여줘야 하는 예제로 정하겠다.
이 경우도 3단계로 나뉘는데 전 예제와 다 동일하지만 3단계인 메뉴에 들어갈 아이템을 만들어 줄 때만 다르다.
코드를 보면 아래와 같다
DropdownMenu(
modifier = Modifier.fillMaxWidth(),
expanded = isDropBoxShow,
onDismissRequest = { isDropBoxShow = false },
content = {
// DropdownMenu의 MenuItem
DropdownMenuItem(
text = {
Text(text = "사과")
},
onClick = {
Toast.makeText(context, "사과", Toast.LENGTH_SHORT).show()
}
)
DropdownMenuItem(
text = {
Text(text = "바나나")
},
onClick = {
Toast.makeText(context, "바나나", Toast.LENGTH_SHORT).show()
}
)
DropdownMenuItem(
text = {
Text(text = "딸기")
},
onClick = {
Toast.makeText(context, "딸기", Toast.LENGTH_SHORT).show()
}
)
}
)
코드와 영상을 보다시피 훨씬 더 이쁘고 간편한 걸 느낄 수 있다!
이렇게 Compose DropdownMenu를 알아봤는데 만약 공부를 안 했더라면 DropDownMenuItem를 사용 안 하고 일일이 만들어 줬을 거 같은데 역시 지금 당장 사용하지 않더라도 미리 한번 알아놓는 게 좋다!
참고
https://kotlinworld.com/249#Compose%EC%9D%98%20DropDownMenu-1