3 분 소요

안드로이드 Menu

안드로이드에서는 다양한 Menu들을 제공하여 편하게 옵션들을 보여줄 수 있다. 최근에는 사용자 경험이 바뀌어 Menu들을 통하여 옵션 세트들을 보여주는 방식이 변경이 되었지만 기본이 되는 Menu들의 각 차이점과 사용법을 알아 보려고 한다.

안드로이드에서 Menu는 크게 Option, Context, Popup로 구현할 수 있다.

Options Menu

화면 상단의 툴바의 흔히 점 3개로 볼 수 있는 버튼을 누르면 나타나는 Menu이다.

Context Menu

View를 길게 눌렀을 때 나타나는 Floating Menu이다.

Popup Menu

View를 눌렀을 때 나타나는 Floating Menu이다.


Menu

안드로이드에서 Menu를 XML 파일에서 정의하고 Acitivty나 Fragment에서 Menu 리소스를 객체로 로드하여 사용할 수 있다.

Menu를 정의하기 위해서는 프로젝트의 res/menu directory에서 XML파일을 생성하고 해당 Menu에서 사용하는 요소들은 다음과 같다.

  • <menu>
    • <item>, <group>을 하위 요소로 가지는 메뉴 항목의 컨테이너이다.
  • <item>
    • Menu 내 단일 요소를 나타내며 속성들을 지정하여 여러가지 설정이 가능하다.
    • Attribute
      • id : item의 고유의 id값으로 요소를 구분할 때 사용
      • showAsAction : v3.x 이상을 사용하며, 메뉴를 ActionBar나 ToolBar 에 보여줄지 여부를 지정 (ifRoom, always, never, withText)
      • menuCategory : menu category를 정의하는 데 사용
      • title : menu에 보여줄 이름 문자열
      • titleCondensed : 이름 문자열이 너무 길었을 때 사용하는 문자열
      • icon : drawable icon
  • <group>
    • <item>을 분류하기 위한 투명한 컨테이너이다. (선택사항) group을 통하여 분류된 item들의 가시성 등 여러 속성을 공유할 수 있다.

메뉴파일을 생성하기 위해서는 res -> new -> Android Resource File 로 생성 할 수 있다.

menu xml에서 item 태그 안에 menu를 중첩하여 sub menu 또한 구성이 가능하다.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/example_item"
        android:title="안녕 메뉴아이템" />
    <group android:id="@+id/example_group">
        <item
            android:id="@+id/example_item2"
            android:title="그룹 내부 아이템 1" />
        <item
            android:id="@+id/example_item3"
            android:title="그룹 내부 아이템 2" />
    </group>
    <item android:id="@+id/example_submenu" android:title="상위 메뉴">
        <menu>
            <item android:id="@+id/item_exit" android:title="종료" />
        </menu>
    </item>
</menu>

Option Menu

Option Menu는 onCreateOptionsMenu()onCreateOptionsMenu() 콜백을 통하여 등록할 수 있다.

class MainActivity : AppCompatActivity() {
    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
    }

    // Menu xml을 생성 한다.
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        val inflater = menuInflater
        inflater.inflate(R.menu.optionmenu, menu)
        return super.onCreateOptionsMenu(menu)
    }

    // 각 요소는 고유의 등록한 id값으로 체크하여 사용한다.
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == R.id.item_exit) {
            finish()
        } else {
            Toast.makeText(this, "Hello Menu, ${item.title}", Toast.LENGTH_SHORT).show()
        }
        return super.onOptionsItemSelected(item)
    }
}

Context Menu

Context Menu는 버튼과 같은 특정 뷰를 사용자가 길게 눌렀을 때 활성화 된다.

Context Menu는 Option Menu와 유사하게 onCreateContextMenu()onContextItemSelect() 콜백을 등록하지만 registerForContextMenu(getListView()) 를 통하여 Context Menu와 연결해야하는 View 를 등록한다.

class MainActivity : AppCompatActivity() {
    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
        // Context Menu를 View에 등록한다.
        registerForContextMenu(binding.contextMenuBtn)
    }

    // Menu xml을 생성 한다.
    override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
        super.onCreateContextMenu(menu, v, menuInfo)
        
        menuInflater.inflate(R.menu.contextmenu, menu)
    }

    override fun onContextItemSelected(item: MenuItem): Boolean = with(binding) {
        when(item.itemId){
            R.id.context_menu_blue -> contextMenuBtn.setTextColor(Color.BLUE)
            R.id.context_menu_red -> contextMenuBtn.setTextColor(Color.RED)
            R.id.context_menu_green -> contextMenuBtn.setTextColor(Color.GREEN)
        }
        return super.onContextItemSelected(item)
    }
}

Popup Menu는 특정 View를 눌렀을 때 활성화 된다.

Option, Context와는 다르게 PopupMenu 를 인스턴스화 하여 View에 생성하여 사용한다. PopupMenu를 보여주기 위해서는 show() 를 호출해야 한다.

PopupMenu에서는 PopupMenu.OnMenuItemClickListener 인터페이스를 구현한 후 setOnMenuItemclickListener() 를 호출하여 PopupMenu에 등록하여 사용자가 항목을 누르면 onItemClick() 콜백을 호출하도록 한다.

// Implement OnMenuItemClickListener
class MainActivity : AppCompatActivity(), OnMenuItemClickListener {
    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        with(binding) {
            // Popup Menu 생성
           PopupMenu(this@MainActivity, binding.popupMenuBtn).apply { 
                inflate(R.menu.popupmenu)
                setOnMenuItemClickListener(this@MainActivity)
                show()
            }
        }
    }

    override fun onMenuItemClick(menuItem: MenuItem): Boolean {
        when (menuItem.itemId) {
            R.id.popup_menu1 -> {
                Toast.makeText(this@MainActivity, "메뉴 1 클릭", Toast.LENGTH_SHORT).show()
            }
            R.id.popup_menu2 -> {
                Toast.makeText(this@MainActivity, "메뉴 2 클릭", Toast.LENGTH_SHORT).show()
            }
            else -> {
                Toast.makeText(this@MainActivity, "메뉴 3 클릭", Toast.LENGTH_SHORT).show()
            }
        }
        return false
    }
}

두 번째 방법으로는 Popup Menu를 생성하하고 setOnMenuItemClickListener() 를 호출하여 사용할 수 있다.

class MainActivity : AppCompatActivity() {
    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        with(binding) {
            popupMenuBtn.setOnClickListener {
                val popupMenu = PopupMenu(this@MainActivity, it)
                menuInflater.inflate(R.menu.pupupmenu, popupMenu.menu)
                // 콜백 메소드 구현
                popupMenu.setOnMenuItemClickListener { menuItem ->
                    when (menuItem.itemId) {
                        R.id.popup_menu1 -> {
                            Toast.makeText(this@MainActivity, "메뉴 1 클릭", Toast.LENGTH_SHORT).show()
                        }
                        R.id.popup_menu2 -> {
                            Toast.makeText(this@MainActivity, "메뉴 2 클릭", Toast.LENGTH_SHORT).show()
                        }
                        else -> {
                            Toast.makeText(this@MainActivity, "메뉴 3 클릭", Toast.LENGTH_SHORT).show()
                        }
                    }
                    false
                }
                // show() 를 호출하여 Popup Menu를 보여준다.
                popupMenu.show();
            }
        }
    }
}


References

맨 위로 이동 ↑

댓글남기기