특정 view 에서 key event 를 받기 위해 dispatchKeyEvent 를 사용하려고 했는데요, 그런데 예상과 달리 dispatchKeyEvent 가 호출이 안 되는 문제가 있었어요.         1. 원인 호출이 안된 이유는 Focu...

[안드로이드] View dispatchKeyEvent 호출이 안 되는 경우

 


특정 view 에서 key event 를 받기 위해 dispatchKeyEvent 를 사용하려고 했는데요,

그런데 예상과 달리 dispatchKeyEvent 가 호출이 안 되는 문제가 있었어요.

 

 

 

 

1. 원인

호출이 안된 이유는 Focus 문제였습니다..ㅠㅠ

Android Developer: dispatchKeyEvent

문서에서 확인된 내용으로 dispatchKeyEvent 가 호출되기 위해서

"if this view has focus, if will dispatch to itself "

해당 View 가 Focus 를 가져야 한다고 하네요.

 

 

 

2. 해결 방법

dispatchKeyEvent 가 호출되야하는 View 에 Focus 를 줘야하는데

requestChildFocus 를 사용해서 해결할 수 있었습니다.

(혹시 또 다른 방법이 있다면 댓글 남겨주세요..!)

Android Developer: requestChildFocus

 


 

3. 예제

키 이벤트를 받는 뷰(KeyEventView) 를 추가하여,

뒤로가기 버튼으로 dispatchKeyEvnet 메소드가 잘 호출되는지 확인하였습니다.



MainActivity.kt

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

val keyEventView = KeyEventView(this) // keyEventView

binding.btnAddView.setOnClickListener {
if (!binding.lyContainer.contains(keyEventView)) {
keyEventView.requestChildFocus() // keyEventView Focus
binding.lyContainer.addView(keyEventView)
}
}

binding.btnRemoveView.setOnClickListener {
if (binding.lyContainer.contains(keyEventView)) {
binding.lyContainer.removeView(keyEventView)
}
}
}
}


KeyEventView.kt

class KeyEventView(context: Context?) : LinearLayout(context) {

private var binding: KeyEventViewBinding

init {
binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.key_event_view, this, true)
}

fun requestChildFocus() {
// KeyEvent View Focus
requestChildFocus(binding.root, null)
}

override fun requestChildFocus(child: View?, focused: View?) {
super.requestChildFocus(child, focused)
}

override fun dispatchKeyEvent(event: KeyEvent?): Boolean {

val action = event?.action
val keyCode = event?.keyCode

event?.let {
val result = "keyCode $keyCode, action $action"
binding.tvKeyEvent.text = result
return true
}

return super.dispatchKeyEvent(event)
}
}

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<Button
android:id="@+id/btnAddView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add View"
android:textAllCaps="false" />

<Button
android:id="@+id/btnRemoveView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Remove View"
android:textAllCaps="false" />

<FrameLayout
android:id="@+id/lyContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

</FrameLayout>
</LinearLayout>
</layout>

 

key_event_view.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#A0A0AA"
android:gravity="center"
android:orientation="vertical">

<TextView
android:id="@+id/tvTestView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="KeyEventView"
android:textColor="@color/black"
android:textSize="30dp" />

<TextView
android:id="@+id/tvKeyEvent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="30dp" />
</LinearLayout>
</layout>

 

 

 

0 comments: