ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [UI] Context Menu 사용법
    Android/UI 2021. 9. 18. 17:27

    View를 롱 터치하면 컨텍스트 메뉴가 생성되고 View근처에 뜨게 된다.

    컨텍스트 메뉴를 사용하기 위해 View.onCreateContextMenuListener인터페이스를 구현( onCreateContextMenu메서드)

    뷰에 setOnCreateContextMenuListener(구현객체)로 등록

    롱 터치시 구현객체의 onCreateContextMenu메서드가 호출되어 컨텍스트 메뉴가 호출된다.

    Activity의 onContextItemSelected를 오버라이딩 ( 컨텍스트 메뉴의 메뉴아이템이 선택되면 호출된다 )


    1. 관련된 View의 메서드들과 인터페이스

     

    • setOnCreateContextMenuListener 

    setOnClickListener를 통해 리스너를 등록하고 뷰가 클릭이 되면

    View.OnClickListener구현객체의 onClick에 구현해놓은 내용이 호출되었다.

     

    마찬가지로 setOnCreateContextMenuListener도 뷰가 롱 터치되면

    View.OnCreateContextMenuListener구현객체의 onCreateContextMenu가 호출되어 컨텍스트 메뉴를 생성한다.


    • View.OnCreateContextMenuListener 인터페이스의 onCreateContextMenu메서드

    뷰에 컨텍스트메뉴 리스너를 설정하고 롱터치가 발생하면 onCreateContextMenu메서드가 호출되는데 

    여기서 적절한 컨텍스트 메뉴를 생성해주면 된다.

    abstract fun onCreateContextMenu( menu: ContextMenu!, v: View!, menuInfo: ContextMenu.ContextMenuInfo! ): Unit menu- 현재 만들어질 컨텍스트 메뉴
    v- 어떤 뷰를 위해 컨텍스트 메뉴를 생성하고 있는지( 롱 터치된 뷰)
    menuInfo- 컨텍스트 메뉴의 메뉴 아이템 추가 정보. v에 따라 다르다.

    onCreateContextMenu{
    //뷰에 따라 생성해야할 컨텍스트 메뉴가 다르다면
        if(뷰1){
        	//메뉴1.xml 인플레이션
        }
        if(뷰2){
        	//메뉴2.xml 인플레이션
        }
    }

    Activity또한 View.OnCreateContextMenuListener를 구현했기 떄문에

    Activity에서 onCreateContextMenu메서드를 오버라이딩한후 

    뷰.setOnCreateContextMenuListener( this //액티비티) 로 사용할 수 있다.


    2. 관련된 Activity의 메서드들

    • onCreateContextMenu 메서드(롱 터치시 onCreateContextMenu를 통해 컨텍스트 메뉴가 만들어지고 화면 출력됨)

    Activity는 View.OnCreateContextMenuListener를 구현하고 있다.

    다음과 같은 방식으로 View에 컨텍스트 메뉴 리스너를 등록할 수 있다.

     

    MainActivity

    //MainActivity
    
    //리스너 메서드 구현
    override fun onCreateContextMenu(...){}
    
    onStart메서드 {
    	뷰1.setOnCreateContextListener(this)
        	뷰2.setOnCreateContextListener(this)
    }
    
    onStop메서드{
    	뷰1.setOnCreateContextListener(null)
        	뷰2.setOnCreateContextListener(null)
    }

    뷰1, 뷰2는 이제 롱 클릭이 되면 액티비티에 구현된 onCreateContextMenu가 호출되어 컨텍스트 메뉴가 생성된다.

     

    RecyclerView의 itemView에 컨텍스트 메뉴를 사용하려면 

    ViewHolder 생성자 내에서 따로 리스너를 만들어 사용할 수 있다.

     


    • registerForContextMenu(view), unregisterForContextMenu(view)

    바로 위의 뷰1.setOnCreateContextListener(this)는 registerForContextMenu(뷰1)과 동일하다.

     

    Activity.java

    Activity의 구현체를 리스너로 설정할 수도있으며, 직접 객체를 만들어서 리스너를 설정할 수도있다.

     

    View가 롱 터치되고 설정된 리스너의 콜백 메서드 onCreateContextMenu를 통해 컨텍스트 메뉴를 만들게 된다.

    작업이 끝나면 컨텍스트 메뉴가 화면에 출력되고 사용자가 아이템을 선택하면 onContextItemSelected메서드가 호출된다.

     


    • onContextItemSelected(item: MenuItem) : Boolean

    만들어진 컨텍스트 메뉴안의 메뉴 아이템이 선택되면 호출된다.


    • onContextMenuClosed(menu: Menu): Unit

    컨텍스트 메뉴가 화면에 보이는 상태에서 메뉴 아이템이 선택되지 않고 back버튼, 또는 컨텍스트 메뉴 바깥의 공간을 터치하면 호출된다.


    테스트 

     

    context_menu1.xml

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/context_menu_item1"
            android:title="컨텍스트 메뉴 아이템1" />
        <item
            android:id="@+id/context_menu_item2"
            android:title="컨텍스트 메뉴 아이템2" />
        <item
            android:id="@+id/context_menu_item3"
            android:title="컨텍스트 메뉴 아이템3" />
        <item
            android:id="@+id/context_menu_item4"
            android:title="컨텍스트 메뉴 아이템4" />
        <item
            android:id="@+id/context_menu_item5"
            android:title="컨텍스트 메뉴 아이템5"/>
    
    </menu>


    context_menu2.xml

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/context_menu2_item1"
            android:title="컨텍스트 메뉴2 아이템1" />
        <item
            android:id="@+id/context_menu2_item2"
            android:title="컨텍스트 메뉴2 아이템2" />
        <item
            android:id="@+id/context_menu2_item3"
            android:title="컨텍스트 메뉴2 아이템3" />
        <item
            android:id="@+id/context_menu2_item4"
            android:title="컨텍스트 메뉴2 아이템4" />
        <item
            android:id="@+id/context_menu2_item5"
            android:title="컨텍스트 메뉴2 아이템5"/>
    
    </menu>


    activity_test.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".TestActivity">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:background="#e2e2e2"
            android:gravity="center"
            android:text="타입1"
            app:layout_constraintBottom_toTopOf="@+id/textView2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.497"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/textView2"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:background="#e2e2e2"
            android:gravity="center"
            android:text="타입2"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

     

    TestActivity.kt

    package com.source.ui.contextmenutext
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.util.Log
    import android.view.*
    import android.widget.TextView
    import android.widget.Toast
    
    class TestActivity : AppCompatActivity() {
    
        lateinit private var textView: TextView
        lateinit private var textView2: TextView
    
        private fun log(str: String) { //로그 출력
            Log.d("ContextMenu", str)
        }
    
        private fun toast(str: String) { //토스트 출력
            Toast.makeText(this, str, Toast.LENGTH_SHORT).show()
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            log("onCreate")
            setContentView(R.layout.activity_test)
            textView = findViewById<TextView>(R.id.textView)
            textView2 = findViewById<TextView>(R.id.textView2)
        }
    
        override fun onStart() { //리스너 등록 -
            super.onStart()
            log("onStart")
    
            registerForContextMenu(textView) //Activity method
            //= textView.setOnCreateContextMenuListener(this)
            registerForContextMenu(textView2) //Activity method
            //= textView2.setOnCreateContextMenuListener(this)
        }
    
        override fun onStop() { //리스너 해제
            super.onStop()
            log("onStop")
    
            unregisterForContextMenu(textView)
            //= textView.setOnCreateContextMenuListener(null)
            unregisterForContextMenu(textView2)
            //= textView2.setOnCreateContextMenuListener(null)
        }
    
        //Activity implements View.OnCreateContextMenuListener
        override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) { //롱 터치시 호출됨-> 컨텍스트 메뉴 생성
            super.onCreateContextMenu(menu, v, menuInfo)
            log("onCreateContextMenu")
    
            val menuInflater = this.getMenuInflater()
            if (v != null) { //View에 따라 분기
                if (v.id == R.id.textView) {
                    menuInflater.inflate(R.menu.context_menu1, menu)
                }
                if (v.id == R.id.textView2) {
                    menuInflater.inflate(R.menu.context_menu2, menu)
                }
            } else {
                Toast.makeText(this, "onCreateContextMenu View parameter is null", Toast.LENGTH_SHORT).show()
            }
        }
    	
        //어떠한 컨텍스트 메뉴인지 알수 없어 적절히 분기해야한다.
        override fun onContextItemSelected(item: MenuItem): Boolean {
            log("onContextItemSelected")
    
            when (item.itemId) {
    
                //컨텍스트 메뉴가 context_menu1.xml일때
                R.id.context_menu_item1 -> {
                    toast("1")
                    return true
                }
                R.id.context_menu_item2 -> {
                    toast("2")
                    return true
                }
                R.id.context_menu_item3 -> {
                    toast("3")
                    return true
                }
                R.id.context_menu_item4 -> {
                    toast("4")
                    return true
                }
                R.id.context_menu_item5 -> {
                    toast("5")
                    return true
                }
    
                //컨텍스트 메뉴가 context_menu2.xml일때
                R.id.context_menu2_item1 -> {
                    toast("one")
                    return true
                }
                R.id.context_menu2_item2 -> {
                    toast("two")
                    return true
                }
                R.id.context_menu2_item3 -> {
                    toast("three")
                    return true
                }
                R.id.context_menu2_item4 -> {
                    toast("four")
                    return true
                }
                R.id.context_menu2_item5 -> {
                    toast("five")
                    return true
                }
                else -> return false
            }
            //boolean Return false to allow normal context menu processing to proceed, true to consume it here.
        }
        
    }

     

     

    'Android > UI' 카테고리의 다른 글

    [UI] RatingBar  (0) 2021.09.27
    [UI] 스타일과 테마 - 1  (0) 2021.09.24
    [UI] Touch Event (2) - 터치 이벤트의 시작과 끝  (0) 2021.09.16
    [UI] Touch Event (1) - 터치 이벤트 전달 과정  (0) 2021.09.15
    [UI] RecyclerView 공부  (0) 2021.07.31

    댓글

Designed by Tistory.