본문 바로가기

MOBILE/android

[Android] option menu, context menu, popup menu: Menu 모음 및 사용

 

안드로이드에서 제공하는 메뉴는 크게 3가지 형태이다.

 

1. option menu

: action bar에 달려있는 기본 메뉴 -> 앱 전체에 작용한다. 액티비티에 종속되기 때문에 액티비티별로 메뉴가 다르게 설정할 수도 있음

2. context menu

: view 를 길게 누르면 나타나는 메뉴 -> 현재 선택된 view에만 작용한다.

3. popup menu

: view를 클릭하면 나타나는 메뉴 -> 현재 화면에 있는 모든 view에 작용한다.

 


menu 사용하기

 

1. option menu

크게 두개의 메서드를 오버라이딩해서 구현해야 한다.

- onCreateOptionsMenu

- onOptionsItemSelected

 

(1) onCreateOptionsMenu: Menu 정의

public boolean onCreateOptionsMenu(Menu menu)

여기서 menu item을 추가할 수 있다. menu class의 add 메서드를 쓰면 된다.

 

 

하위 menu를 넣고 싶은 경우 SubMenu를 가져와서 addSubMenu 메서드로 menu에 추가하면 된다.

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(Menu.NONE,1,Menu.NONE,"1");
        menu.add(Menu.NONE,2,Menu.NONE,"2");
        SubMenu subMenu=menu.addSubMenu("sub menu");
        menu.add(Menu.NONE,3,Menu.NONE,"3");
        return super.onCreateOptionsMenu(menu);
    }

 

 

xml에 menu를 정의한 경우에는 다음과 같이 그걸 MenuInflater로 inflate해서 초기화한다.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater=getMenuInflater();
    inflater.inflate(R.menu.menu_main,menu);
    return super.onCreateOptionsMenu(menu);
}

xml에 ui를 정의하는게 많기 때문에 이 방법이 좋다.

 

 

(2) onOptionsItemSelected: Menu 처리

public boolean onOptionsItemSelected(@NonNull MenuItem item)

 

여기서 각각의 menu item에 해당하는 작업을 정의하고 처리하면 된다.

menu item의 id는 getItemId 메서드로 가져온다.

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()){
        case R.id.item1:
            Toast.makeText(this, "메뉴 1 선택", Toast.LENGTH_SHORT).show();
            return true;
        case R.id.item2:
            Toast.makeText(this, "메뉴 2 선택", Toast.LENGTH_SHORT).show();
            return true;
        case R.id.item3:
            Toast.makeText(this, item.getTitle()+" 선택", Toast.LENGTH_SHORT).show();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

getTitle 메서드를 활용하면 menu 제목을 얻을 수 있다.

Q: get이 있으니 set도 있나요?

A: 당연함. setTitle로 지정도 가능하다.

 

 


2. context menu

버튼, edit text, image 등 view를 길게 누르면 나타나는 메뉴다.

이때 메뉴는 누른 view에 한해서 작동한다.

'long-touch here button'을 누르면 나오는 context menu

 

context menu는 총 3가지가 필수적이다.

option menu와 비교했을 때 추가되어야할 점은 특정 view에 menu를 연결해주는 것이라는 것이 감이 올것이다. (아님 말고)

그게 바로 registerForContextMenu이다. 파라미터에는 등록시킬 view를 쓴다.

나머지 두개는 option menu와 동일한 역할을 한다.

 

- registerForContextMenu

- onCreateContextMenu

- onContextItemSelected

 

 

(1) registerForContextMenu: view에 menu를 연결시킴

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    mButton=findViewById(R.id.test1);
    registerForContextMenu(mButton);
}

 

메서드의 파라미터로는 등록하고 싶은 view 객체를 쓰면 된다.

예를 들어, Button을 눌렀을 때 context menu가 뜨게 하고 싶으면 button을 등록한다.

 

 

(2) onCreateContextMenu: Menu 정의

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
    MenuInflater inflater=getMenuInflater();
    inflater.inflate(R.menu.menu_main,menu);
    menu.setHeaderTitle("텍스트 색상 변경");
    
    super.onCreateContextMenu(menu, v, menuInfo);
}

option menu와 마찬가지로 xml에 쓴 메뉴를 MenuInflater로 inflate해서 초기화한다.

이때 setHeaderTitle 메서드를 사용하면 menu 헤더에 title을 보여주도록 설정할 수 있다.

 

 

(3) onContextItemSelected: Menu 처리

@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
    Toast.makeText(this, item.getTitle(), Toast.LENGTH_SHORT).show();

    return super.onContextItemSelected(item);
}

option menu와 마찬가지로 메뉴를 선택했을 때의 동작을 처리한다.

여기서는 간단하게 item의 title을 getTitle()메서드로 가져와서 토스트로 보여주도록 설정했다.


 

3. popup menu

 

popup menu는 다른 menu들과 달리 인터페이스 구현이 필요하다.

3가지 단계가 포인트이다.

- popup menu 객체 생성

- MenuInflater로 xml로 쓴 menu 가져와서 초기화

- OnMenuItemClickListener 구현해서 popup menu 객체에 리스너 등록

 

 

안드로이드 공식 문서에는 이렇게 나와있다.

https://developer.android.com/reference/android/widget/PopupMenu

이 중에서 menu를 구현하고 싶다면 onMenuItemClickListener를 구현해야한다.

인터페이스이므로 다음 메서드를 오버라이딩해서 구현해야한다.

필수 작업이다. 여기서 menu 처리를 하면 된다.

public boolean onMenuItemClick(MenuItem menuItem)

 

버튼에 popup menu를 등록하는 예시로 알아보자

// 버튼 클릭 리스너
mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    	// Popup menu 객체 생성
        PopupMenu popup=new PopupMenu(getApplicationContext(),view);
        
        // menu inflater로 xml의 menu 가져와서 초기화
        MenuInflater inflater=getMenuInflater();
        inflater.inflate(R.menu.menu_main, popup.getMenu());
        
        // popup menu에 listener 구현해서 등록
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                switch (menuItem.getItemId()){
                    case R.id.item1:
                        mButton.setTextColor(Color.RED);
                        break;
                    case R.id.item2:
                        mButton.setTextColor(Color.GREEN);
                        break;
                }
                return false;
            }
        });
        popup.show();

    }
});

 

 

나는 내부 인터페이스로 생성했지만 mainactivity에서 Implements 해서 구현해도 상관없다.

 

끝!