2023.02.15 - 안드로이드 앱개발자 과정

CHA·2023년 2월 17일
0

Android



우리가 핸드폰을 사용할 때, 모든 정보들이 한 화면에 표시되지는 않습니다. 공간이 부족하기 때문이죠. 그래서 보기에도 깔끔하고 효율적으로 정보들을 관리하기 위한 Menu 를 사용해봅시다!


Option Menu

앱의 상단쪽을 보면 앱의 제목과 여러가지 메뉴들을 본적이 있을겁니다. 이 상단바를 Action Bar 라고 하며, 그 윗부분에 배터리 등의 정보를 표시하는 바를 Status Bar 라고 합니다. 이번에는 액션바에 붙는 메뉴들인 Option Menu 에 대해 알아봅시다.

액션바에 옵션메뉴 추가하기

옵션 메뉴를 추가하기 전에 간단하게 옵션메뉴의 구조부터 알아봅시다. 우리가 xml 에서 화면을 구성할 때, 여러개의 뷰들을 사용하여 화면구성을 할 수 있도록 레이아웃 하나를 이용하고 그 레이아웃안에 여러개의 뷰들을 집어넣어 사용합니다. 옵션메뉴도 이와 비슷하게 Menu 판이 존재하고, 이 메뉴판 위에 MenuItem 을 집어넣는 구조 입니다.

onCreate() 메서드가 실행이 된 후에 자동으로 Option Menu 를 만드는 작업을 하는 콜백메서드가 있습니다. 바로 onCreateOptionMenu() 입니다. 평소에는 따로 적어주지 않았을 뿐 자동으로 실행되는 메소드 입니다. 그러면 이 메소드를 이용하여 옵션메뉴를 추가해봅시다. 먼저 java 를 이용하여 추가해볼까요?

  • JAVA
    자바로 옵션메뉴를 추가하기 위해서는 add() 메서드가 필요합니다. 다음 코드와 같이 작성하면 옵션메뉴를 추가할 수 있습니다.
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
         menu.add("aa");
         return super.onCreateOptionsMenu(menu);
    }

그런데 자바코드로 옵션메뉴를 추가하려니 아이콘이나 id 와 같은 식별자를 지정할 때 굉장히 번거롭습니다. 또한 메뉴가 많아지기라도 한다면, 스윙 때와 마찬가지의 번거로움을 느낄 수 있습니다. 그래서 우리는 xml 언어로 Option Menu 를 설계하고 객체로 만들어서 사용해봅시다.

  • XML
    xml 을 이용하여 옵션메뉴를 구성하려면 먼저 옵션메뉴가 어떻게 생겨먹은 옵션메뉴인지를 정해줘야 합니다. 그리고 그 정보들을 가져와주는 객체를 하나 만듭니다. 그리고 그 객체에게 우리가 만든 옵션 메뉴의 정보들을 어디에다 붙여줄껀지와 어떤 옵션 메뉴의 정보인지를 알려주고 만들어 달라고 할겁니다. 자 그럼 코드를 봅시다.
--------- option.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/menu_search"
        android:title="search"
        android:icon="@drawable/ic_action_search"
        app:showAsAction="always"/>

    <item
        android:id="@+id/menu_add"
        android:title="add"
        android:icon="@drawable/ic_action_add"
        app:showAsAction="ifRoom"/>

    <item
        android:id="@+id/menu_help"
        android:title="help"
        app:showAsAction="never"/>

</menu>

위 코드는 옵션메뉴의 모습을 그려낸 xml 코드입니다. 옵션메뉴가 어떻게 생겨먹은아이인지 정하기 위해 res 폴더 안에 menu 폴더를 생성해 준 뒤, 메뉴 리소스 파일로 option.xml 을 하나 만듭니다. 옵션메뉴에는 대충 서치하는 메뉴와 추가하는 메뉴, 도움말 메뉴 정도가 있다고 합시다. 각각의 id 값을 하나씩 지정해주고, title 속성으로 제목을 지정해줍니다.

---------- MainActivity.java 
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option,menu);

        return super.onCreateOptionsMenu(menu);
    }
}

옵션메뉴의 모양을 결정짓는 xml 설계도면을 만들었으니 이제 그 설계도면을 가져다가 실제로 옵션 메뉴를 만드는 작업을 해야합니다. 그 작업을 해주는 객체가 MenuInflater 객체 입니다. inflater 참조변수에 객체를 넣어주기 위해 getMenuInflater() 메서드로 객체를 소환합시다. 그런뒤에 inflater.inflate(R.menu.option,menu) 와 같이 inflate() 메서드를 이용하여 옵션메뉴의 xml 파일을 Menu 객체에 붙여주면 됩니다. 이렇게 하면 옵션 메뉴가 완성됩니다.

옵션 메뉴를 만드는 과정을 도식화한 그림입니다. 이 그림을 잘 기억해둡시다.


SearchView

서치뷰는 옵션 메뉴의 일종입니다. 그래서 서치뷰를 만드는 방법은 옵션메뉴를 만드는 방법과 동일합니다. 이번에는 서치뷰의 ID 값을 가져와서 서치뷰를 제어해보고, 서치뷰의 리스너를 설정해 검색 기능의 일부분을 만들어 봅시다.

SearchView 모양 만들기

먼저 옵션메뉴처럼 xml 을 통해 서치뷰의 모양부터 잡아줍시다.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/menu_search"
        android:title="SEARCH"
        app:actionViewClass="androidx.appcompat.widget.SearchView"
        app:showAsAction="always"/>
</menu>

actionViewClass 속성을 이용하여 서치뷰의 기능을 가져옵니다. 그리고 showAsAction 속성을 이용해 액션바에 표시형식을 지정합시다.

SearchView 를 메뉴에 붙이기

그러면 이제 보여주는 작업은 다 끝났으니, 서치버튼을 만들어 옵션메뉴에 붙여 봅시다.

public class MainActivity extends AppCompatActivity {

    SearchView searchView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
//        MenuInflater menuInflater = getMenuInflater();
//        menuInflater.inflate(R.menu.option_search,menu);

        getMenuInflater().inflate(R.menu.option_search,menu);
        MenuItem menuItem = menu.findItem(R.id.menu_search);
        searchView = (SearchView) menuItem.getActionView();

        searchView.setQueryHint("이름을 입력하세요");

        return super.onCreateOptionsMenu(menu);
    }
}

자 그럼 먼저 옵션메뉴를 만들듯 MenuInflater 객체를 이용하여 서치뷰도 만들어봅시다. 원래는 getMenuInflater() 를 이용하여 MenuInflater 객체를 소환하고, 소환된 객체의 참조변수의 메서드인 inflate 를 이용하여 메뉴를 만드는 작업을 거쳤습니다. 같은 원리이긴 하지만 코드를 조금 더 효율적으로 사용하여 다음과 같이 작성했습니다.
getMenuInflater().inflate(R.menu.option_search,menu);
이렇게 작성하면 MenuInflater 의 참조변수를 따로 만들어주지 않아도 됩니다.

그 이후에 우리는 검색기능을 만들어야 하므로, SearchView 의 ID값이 필요합니다. 그래야 SearchView 참조변수를 통해 이것저것 제어해 볼 수 있으니까요. 그 작업을 해봅시다.

먼저, id 값을 가져오기 위해서 find 해주어야 합니다. 단 기존에 findViewById 는 사용할 수 없습니다. 우리는 지금 activity_main.xml 에 있는 뷰를 찾아오는것이 아닌 액션바에 있는 서치뷰를 찾아야하기 때문입니다. 그리고 일단 그 서치뷰는 Menu 객체가 가지고 있는 MenuItem 객체 안에 들어있는 뷰 입니다. 그래서 우리는 서치뷰를 찾기 이전에 MenuItem 을 먼저 찾아주어야 합니다. 그리고 그 작업을 위해 findItem() 메서드를 사용했습니다.
MenuItem menuItem = menu.findItem(R.id.menu_search);
즉, Menu 객체에게 MenuItem 객체를 우리가 원하는 xml 파일에서 찾아달라 부탁한 과정입니다. 그렇게 찾은 MenuItem 객체를 이용하여 이제 서치뷰를 찾을 차례입니다.
searchView = (SearchView) menuItem.getActionView();
이렇게 하면 이제 서치뷰의 id 값을 받아와 java 를 이용해 서치문을 제어할 수 있게됩니다. 위 코드 처럼 searchView.setQueryHint() 처럼 검색어 입력란에 힌트를 줄 수도 있습니다.

SearchView 의 리스너 설정하기

이제 리스너를 통해 여러가지 제어를 해봅시다.

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        Toast.makeText(MainActivity.this, "검색어 : "+query, Toast.LENGTH_SHORT).show();
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        Toast.makeText(MainActivity.this, "검색어 : "+newText, Toast.LENGTH_SHORT).show();
        return false;
    }
});

onQueryTextSubmit 메서드는 소프트 키보드의 돋보기 버튼을 눌렀을 때, 즉 검색어 입력이 완료되었을 때 발생하는 이벤트 입니다. 검색어 입력이 완료되었으니 검색 알고리즘을 사용하여 검색 코드를 작성해주면 될것 같습니다. 그 부분은 나중에 한번 다뤄봅시다.

onQueryTextChange 메서드는 검색어를 입력할 때 글씨가 변화하는 순간마다 발생하는 이벤트 입니다. 이 메서드를 이용하면 검색어 자동완성 기능등을 구현할 수 있을것 같네요.


완성된 SearchView 를 보면, 평상시에는 아이콘 이었다가 사용자가 서치뷰를 누르면 에디트텍스트로 변하는 모습을 볼 수 있습니다. 또한 서치뷰에 우리가 따로 아이콘을 넣어주지 않았음에도 서치뷰는 이미 아이콘을 가지고 있습니다. 물론 프리뷰에는 따로 보이지 않지만 실행을 시켜보면 이미 아이콘을 가지고 있음을 알 수 있습니다.


ActionView

앞서 옵션메뉴를 설명할 때, 옵션메뉴는 액션 뷰의 일종이라고 하였습니다. 우리는 이 액션뷰를 만들수도 있는데요, 한번 어떤식으로 만들게 되는지 알아봅시다. 사실 옵션 메뉴와 만드는 방법에서 큰 차이는 없습니다.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@drawable/thumb_moana"/>

    <EditText
        android:id="@+id/actionview_et"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:hint="검색어 입력"
        android:ems="10"
        android:inputType="text"
        android:imeOptions="actionSearch"/>

</LinearLayout>
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.option_actionview,menu);
    MenuItem item = menu.findItem(R.id.menu_action);
    LinearLayout layout = (LinearLayout) item.getActionView();
    actionViewEt = layout.findViewById(R.id.actionview_et);
    actionViewEt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
            if(i == EditorInfo.IME_ACTION_SEARCH){
                String message = actionViewEt.getText().toString();
                Toast.makeText(MainActivity.this, "검색어 : " + message, Toast.LENGTH_SHORT).show();
            }
            return false;
        }
    });
    return super.onCreateOptionsMenu(menu);
}

옵션메뉴와 똑같이 MenuInflater 객체를 통해 액션뷰를 만들 수 있습니다. 그리고 getActionView() 를 통해 서치뷰의 id 값을 찾아줬던것 처럼, 리니어 레이아웃의 id 값을 찾아주었습니다.

우리가 하고싶은건 리니어 레이아웃 안에 배치되어있는 이미지 뷰와 에디트텍스트 뷰에 대한 제어 입니다. 그래서 findViewById() 메서드를 활용하여 이미지뷰와 에디트뷰의 id 값을 가져와야합니다. 근데 옵션메뉴때와 마찬가지로 에디트뷰와 이미지뷰는 activity_main.xml 위에 있는 뷰들이 아닌, 다른 xml 파일에 있기 때문에 먼저 리니어 레이아웃의 id 값을 가지고 온 것입니다.

그런다음 setOnEditorActionListener 을 통해 에디트 텍스트의 리스너를 붙여주고, 검색어를 입력한 뒤 토스트 메시지를 띄워주었습니다.


ActionMode

액션모드 메뉴는 기존의 액션바 위로 새로운 액션바를 만들어 옵션메뉴를 붙이는 방식입니다. 이또한 옵션 메뉴의 일종이고, 만드는 방법은 새로운 액션바에 들어갈 옵션 메뉴를 xml 설계해주고, 자바 코드로 startActionMode() 메서드를 호출하면 됩니다. 액션 뷰를 만드는 과정과 크게 다르지 않기 때문에 가벼운 마음으로 봅시다.

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/menu_share"
        android:title="share"
        android:icon="@drawable/ic_action_share"
        />

    <item android:id="@+id/menu_map"
        android:title="map"
        android:icon="@drawable/ic_action_map"/>
</menu>

xml 을 이용하여 액션 모드의 새로운 액션바에 들어갈 옵션메뉴의 설계도를 작성했습니다.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn = findViewById(R.id.btn);

    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActionMode(new ActionMode.Callback() {
                @Override
                public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                    actionMode.getMenuInflater().inflate(R.menu.option_actionmode,menu);
                    actionMode.setTitle("ActionMode");
                    actionMode.setSubtitle("hello");

                    return true; 
                }

                @Override
                public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return false; }

                @Override
                public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                    if(menuItem.getItemId() == R.id.menu_map)
                        Toast.makeText(MainActivity.this, "맵 버튼 클릭", Toast.LENGTH_SHORT).show();
                    else if(menuItem.getItemId() == R.id.menu_share)
                        Toast.makeText(MainActivity.this, "공유 버튼 클릭", Toast.LENGTH_SHORT).show();
                    return false;
                }

                @Override
                public void onDestroyActionMode(ActionMode actionMode) {}
            });
        }
    });
}

+ 모양 버튼을 누르면 startActionMode() 메서드가 호출되면서 액션 모드가 발동 됩니다. 메서드를 호출하면서 추상메소드 구현을 해주어야 하는데요, 다음 4가지의 추상메소드를 구현해야 합니다. onCreateActionMode(), onPrepareActionMode(),onActionItemClicked(), onDestroyActionMode() .

먼저 onCreateActionMode() 은 액션모드가 처음 실행될 때, 메뉴항목들을 만들기 위해 자동으로 실행되는 콜백 메서드 입니다. 단, 처음 만들어질때 딱 한번만 실행됩니다. 그래서 메서드 안쪽의 코드를 보면 actionMode.getMenuInflater().inflate(R.menu.option_actionmode,menu); 을 통해 actionMode 의 메뉴 인플레이터를 통해 우리가 만들었던 액션모드의 모양 설계도를 Menu 객체에 붙여줍니다. 또한 ActionMode 객체를 이용하여 타이틀이나 서브타이틀 또한 변경이 가능합니다. 그리고 메서드의 리턴값이 true 여야만 액션모드가 발동하게 되니 알아둡시다.

두번째로 onPrepareActionMode() 메서드는 액션모드가 시작될 때 발동하는 콜백메서드 입니다. 앞선 onCreateActionMode() 메서드와 다른점은 시작할 때마다 매번 호출된다는 점입니다.

세번째로 onActionItemClicked() 메서드는 액션 모드가 만든 새로운 액션바의 옵션 메뉴가 클릭될때 실행되는 콜백메서드 입니다. 새로운 액션바의 xml 파일에 있는 뷰들의 ID 값을 가져오기 위하여 파라미터로 전달된 MenuItem 객체를 활용합니다.

마지막으로 onDestroyActionMode() 메서드는 이름에서도 알 수 있듯 액션 모드가 없어질 때 실행되는 콜백메서드 입니다.


Context Menu

Context Menu 는 어떤 뷰 객체를 꾸욱 눌렀을 때 나오는 메뉴 입니다. 일단 코드를 먼저 봅시다.

----------- activity_main.xml


<RelativeLayout ... 중략>

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</RelativeLayout>


----------- context.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_save"
        android:title="SAVE"/>
    <item
        android:id="@+id/menu_delete"
        android:title="DELETE"/>
</menu>


----------- MainActivity.java
public class MainActivity extends AppCompatActivity {

    Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = findViewById(R.id.btn);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"버튼이 눌렸습니다",Toast.LENGTH_SHORT).show();
            }
        });
        registerForContextMenu(btn);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.context,menu);

        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(@NonNull MenuItem item) {
        int id = item.getItemId();
        if(id == R.id.menu_save){
            Toast.makeText(this,"save 버튼이 눌렸습니다.",Toast.LENGTH_SHORT).show();
        } else if(id == R.id.menu_delete){
            Toast.makeText(this,"delete 버튼이 눌렸습니다.",Toast.LENGTH_SHORT).show();
        }
        return super.onContextItemSelected(item);
    }
}

먼저, activity_main.xml 파일에서 버튼 객체 하나를 만들어줍시다. 이 버튼을 누르면 토스트 메시지를 하나 띄울거고, 버튼을 꾸욱 누르면 컨텍스트 메뉴가 띄워지게끔 해보겠습니다. 그러면 이제 컨텍스트 메뉴의 모양새를 잡아줘야겠죠? context.xml 파일에서 그 모양을 잡아줬습니다. 메뉴의 아이템들로 SAVA 와 DELETE 를 넣어주었습니다. 각각의 아이템 메뉴들을 클릭하면 토스트 메시지를 띄웁니다.

먼저 이 버튼 객체를 컨텍스트 메뉴로 등록해주는 과정이 필요합니다. 그 과정을 resisterForContextMenu(btn); 을 통해 등록해주었습니다. 이렇게 ContextMenu 로 등록된 객체를 길게 누르면 컨텍스트 메뉴를 만드는 메소드가 자동으로 호출 됩니다.

그리고 이제 컨텍스트 메뉴를 만드는 작업과 메뉴의 아이템을 눌렀을 때의 동작을 구현 해봅시다.
onCreateContextMenu() 메서드를 통해 컨텍스트 메뉴를 만듭니다. 메서드의 첫번째 파라미터는 컨텍스트 메뉴를 붙일 메뉴 객체 입니다. 그리고 두번째 파라미터로 등록된 view 는 버튼 객체를 의미 합니다. 메서드 안쪽을 보면 여기서도 MenuInflater 객체가 사용됩니다. getMenuInflater() 메서드를 이용하여 메뉴 인플레이터의 객체를 소환합시다. 그리고 인플레이터 객체를 이용하여 컨텍스트의 모양을 메뉴 판떼기에 붙여줍니다. 그러면 컨텍스트 메뉴 설정이 완료 되었습니다.

onContextItemSelected() 메서드는 아이템을 눌렀을 때의 동작을 구현해볼 수 있습니다. Menu 객체안에 있는 MenuItem 객체가 파라미터로 전달되었으므로 우리는 각 아이템 뷰들의 ID 값 또한 가져와 제어해볼 수 있습니다.


팝업 메뉴는 사실상 컨텍스트 메뉴 보다 자유롭게 사용해볼 수 있는 메뉴 입니다. 앞서 컨텍스트 메뉴에서 버튼에 붙여 봤으니, 이번에는 텍스트 뷰에 붙여보는 예제를 해봅시다. 앞서 만들었던 컨텍스트 예제와 거의 동일하니 가벼운 마음으로 다시 코드를 봅시다. 일단 먼저 이 팝업 메뉴란 놈이 어떻게 생겨먹은 놈인지 정해줘야겠죠? xml 코드 부터 보겠습니다.

------------- popup.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_info"
        android:title="information"/>
    <item
        android:id="@+id/menu_delete"
        android:title="delete"/>
    <item
        android:id="@+id/menu_modify"
        android:title="modify"/>
</menu>
------------ activity_main.xml
<RelativeLayout
                ... 중략">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MENU"/>

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello Popup"
        android:textColor="@color/black"
        android:textSize="25sp"
        android:padding="8dp"
        android:layout_centerInParent="true"/>

</RelativeLayout>

업로드중..

메뉴 버튼 하나를 만들었습니다. 이 버튼을 누르면 팝업 메뉴가 띄워지게끔 해보겠습니다. 다만, 버튼아래에 팝업메뉴가 띄워지는것이 아닌, 중앙에 있는 텍스트뷰 밑으로 띄워지게끔 해봅시다.

public class MainActivity extends AppCompatActivity {

    Button btn;
    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = findViewById(R.id.btn);
        tv = findViewById(R.id.tv);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                PopupMenu popupMenu = new PopupMenu(MainActivity.this,tv);

                MenuInflater inflater = getMenuInflater();
                inflater.inflate(R.menu.popup,popupMenu.getMenu()); 

                popupMenu.show();
                
                popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem menuItem) {
                        int id = menuItem.getItemId();
                        if(id == R.id.menu_info) Toast.makeText(MainActivity.this,"인포메이션 버튼이 클릭되었습니다.",Toast.LENGTH_SHORT).show();
                        else if(id == R.id.menu_delete) Toast.makeText(MainActivity.this, "삭제버튼이 클릭되었습니다.", Toast.LENGTH_SHORT).show();
                        else if(id == R.id.menu_modify) Toast.makeText(MainActivity.this, "변경버튼이 클릭되었습니다.", Toast.LENGTH_SHORT).show();
                        return false;
                    }
                });
            }
        });
    }
}

버튼 리스너를 하나 만들어 줬으며, onClick() 콜백 메서드 내부에 팝업 메뉴의 객체를 생성해서 텍스트뷰에 붙이는 작업을 해봅시다. PopupMenu popupMenu = new PopupMenu(MainActivity.this,tv); 를 이용하여 팝업 메뉴의 객체를 생성해 주었습니다. 객체의 생성자로 Context 객체 하나와 이 팝업메뉴를 붙일 객체를 전달해줍니다. 우리는 텍스트뷰에 붙일 예정이므로 텍스트뷰의 객체인 tv 를 파라미터로 전달했습니다.

MenuInflater inflater = getInflater(); 를 이용하여 메뉴 인플레이터 객체를 소환시켰습니다. 그리고 그 인플레이터를 이용하여, inflater.inflate(R.menu.popup.xml,popupMenu.getMenu()); 와 같이 인플레이트 하였습니다. 앞선 옵션 메뉴와 컨텍스트 메뉴는 콜백 메서드들을 오버라이드 하여 그 메서드 내부에서 메뉴들을 조작했었습니다. 그리고 그 메서드들은 메뉴 객체의 파라미터에는 메뉴 객체가 있어서 그 메뉴 객체를 이용했습니다. 하지만 팝업 메뉴의 경우에는 오버라이드된 메서드가 없기 때문에 getMenu() 를 통해 메뉴 객체를 소환 시켜주었습니다.

그리고 마지막으로 popupMenu.show(); 를 통해 팝업 메뉴를 보여주고, popupMenu.setOnMenuItemClickListener() 를 통해 팝업 메뉴 아이템들의 클릭 이벤트를 처리 해줄 수 있습니다.

참고자료

https://recipes4dev.tistory.com/141

profile
Developer

0개의 댓글