Image
Android Jetpack Compose UI/Compose UIs

[Android Compose] 1. DropDownMenu 이용해 펼쳐지는 메뉴 만들기

DropDownMenu란?

DropDownMenu는 버튼을 눌렀을 때 선택지를 보여주는 메뉴 아이템이다. 동작은 그림1과 같다.

그림1. Drop Down Menu

 

Compose의 DropDownMenu

Compose의 Material package에서는 compose.ui.window 패키지의 Popup을 활용해서  DropDownMenu를 만드는 것을 지원한다. Popup을 활용함으로써 부모 Composable의 제약사항(크기 등)에 종속되지 않는 컴포저블을 만들 수 있다.

또한 Material package에서는 미리 디자인된 컴포저블인 DropDownMenuItem 또한 지원한다. DropDownMenuItem을 이용하면 DropDownMenu에 들어갈 아이템들을 쉽게 만들 수 있다.

 

우리는 이번 글에서 DropDownMenu와 DropDownMenuItem 두가지를 이용해 DropDownMenu를 만드는 방법을 다룬다.

 

DropDownMenu의 구성요소

DropDownMenu는 다음의 구성요소로 구성되어 있다.

  • expanded : DropDownMenu가 펼쳐졌는지 여부
  • onDismissRequest : DropDownMenu를 닫으라는 명령(Dismiss Request)이 떨어졌을 때의 동작
  • offset : DropDownMenu를 호출하는 Composable의 기준점으로부터의 거리(offset) 설정
  • properties : 백버튼을 눌렀을 때 DropDownMenu를 Dismiss 할 것인지, DropDownMenu의 바깥쪽을 눌렀을 때 Dismiss할 것인지 등의 DropDownMenu의 기본 동작을 정의.
  • content : DropDownMenu안에 들어갈 메뉴 아이템을 넣는 공간

*modifier은 Composable의 공통 사항이므로 다루지 않는다.

@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    properties: PopupProperties = PopupProperties(focusable = true),
    content: @Composable ColumnScope.() -> Unit
)

 

DropDownMenuItem의 구성요소

DropDownMenuItem은 다음의 구성요소로 구성되어 있다.

  • onClick : 메뉴 아이템이 눌렸을 때의 동작 정의
  • enabled : 메뉴 아이템을 클릭 가능하게 할 것인지 여부(눌렸을 때 onClick이 동작할 것인지 여부)
  • contentPadding : DropDownMenuItem에 적용할 Padding값
  • interactionSource : DropDownMenuItem과 사용자와의 Interaction에 대한 이벤트를 관리. 여기서는 클릭 이벤트만 다루므로 따로 다루지 않는다.
  • content : DropDownMenuItem에 표기할 요소 관리 (텍스트 등)
fun DropdownMenuItem(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable RowScope.() -> Unit
)

 

이번 글에서는 기본적인 구성요소들을 이용해 DropDownMenu를 만드는 방법을 다루고

다른 구성요소들에 관해서는 다음 글에서 심화하면서 다룬다.

 

 

DropDownMenu와 DropDownMenuItem을 이용해 DropDownMenu 만들기

DropDownMenu를 위해서는 3가지의 구성요소가 필요하다.

  1. DropDownMenu가 펼쳐졌는지를 제어할 수 있는 변수
  2. DropDownMenu의 펼쳐짐 상태를 제어하기 위한 버튼 혹은 onClick이벤트를 포함한 Composable
  3. DropDownMenu 정의

 

자 이제 만들어보도록 하자.

1. DropDownMenu가 펼쳐졌는지를 제어할 수 있는 Boolean 변수를 Composable 내에 만든다.

@Composable
fun KotlinWorldButtonWithDropDownMenu() {
    // 1. DropDownMenu의 펼쳐짐 상태 정의
    var isDropDownMenuExpanded by remember { mutableStateOf(false) } 
}

isDropDownMenuExpanded 값은 Recomposition이 일어날 때 저장되어야 하고 state가 바뀔 때 Recomposition을 일어나도록 만들어야 한다. Recomposition 시 값을 저장하기 위해 remember을 쓰고, Composable 내에서 State를 인식할 수 있도록 Mutable State를 사용한다.

 

 

2. 1에서 만든 변수를 제어할 수 있는 버튼을 만든다. 클릭 시 변수값이 true로 바뀌어 DropDownMenu가 펼쳐지도록 한다.

@Composable
fun KotlinWorldButtonWithDropDownMenu() {
    // 1. DropDownMenu의 펼쳐짐 상태 정의
    var isDropDownMenuExpanded by remember { mutableStateOf(false) } 

    // 2. DropDownMenu의 Expanded 상태를 변경하기 위한 버튼 정의
    Button(
        onClick = { isDropDownMenuExpanded = true }
    ) {
        Text(text = "Show Menu")
    }
}

Button의 기능은 클릭이 일어났을 때 isDropDownMenuExpanded 변수를 true로 State를 바꾸게 해서 Recomposition이 일어나게 하는 것이다.

 

3. DropDownMenu 정의

@Composable
fun KotlinWorldButtonWithDropDownMenu() {
    // 1. DropDownMenu의 펼쳐짐 상태 정의
    var isDropDownMenuExpanded by remember { mutableStateOf(false) } 

    // 2. DropDownMenu의 Expanded 상태를 변경하기 위한 버튼 정의
    Button(
        onClick = { isDropDownMenuExpanded = true }
    ) {
        Text(text = "Show Menu")
    }

    // 3. DropDownMenu 정의
    DropdownMenu(
        modifier = Modifier
            .wrapContentSize(),
        expanded = isDropDownMenuExpanded,
        onDismissRequest = { isDropDownMenuExpanded = false }
    ) {
    	// 3.1. DropDownMenuItem을 정의하고 눌렸을 때 Hello가 출력되도록 함
        DropdownMenuItem(onClick = {
            println("Hello")
        }) {
            Text(text = "Print Hello")
        }
        // 3.2. DropDownMenuItem을 정의하고 눌렸을 때 KotlinWorld가 출력되도록 함
        DropdownMenuItem(onClick = {
            println("KotlinWorld")
        }) {
            Text(text = "Print KotlinWorld")
        }
    }
}

DropDownMenu의 expanded 파라미터 값으로 1에서 정의한 isDropDropMenuExpanded 변수를 넘기고 onDismissRequest가 발생했을 때 isDropDropMenuExpanded를 false로 변경하여 DropDownMenu가 사라지도록 만든다.

 

내부에는 DropDownMenuItem을 두 개 정의한다. 하나는 눌렸을 때 Hello가 출력되는 아이템이고, 다른 하나는 KotlinWorld가 출력되는 아이템이다.

 

4. 결과

이 세가지를 이용해 코드를 만들어 실행하면 다음과 같이 출력된다.

그림2. DropDownMenu 예시 결과

 

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com