-
[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