常見預設擷取焦點的元件:EditText、Scrollbar
常見不會預設擷取焦點的元件:FrameLayout、LinearLayout、ImageView、Button、TextView
将元件設定clickable = true,則相當于将元件設定為focusable = true
焦點的時間分發機制:焦點的事件分發機制
避免焦點丢失(設定焦點不跑出子View中):大體思路,通過目前已經擷取焦點的view ,以及按鍵的方向,去尋找下一個可以擷取焦點的view,代碼展示:
FocusFinder.getInstance().findNextFocus(ViewGroup root, View focused, int direction)
,如果傳回為null,說明在該方向,擷取不到焦點。可以直接 return true 消費該按鍵,則不會再繼續尋找焦點。
open class FocusLinearLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private lateinit var mFocusView: View
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
var mDirection = 0
if (event.action == KeyEvent.ACTION_DOWN) {
when (event.keyCode) {
KeyEvent.KEYCODE_DPAD_LEFT ->
mDirection = View.FOCUS_LEFT
KeyEvent.KEYCODE_DPAD_RIGHT ->
mDirection = View.FOCUS_RIGHT
KeyEvent.KEYCODE_DPAD_UP ->
mDirection = View.FOCUS_UP
KeyEvent.KEYCODE_DPAD_DOWN ->
mDirection = View.FOCUS_DOWN
}
if (mDirection != 0) {
val findNextFocus = FocusFinder.getInstance().findNextFocus(this, mFocusView, mDirection) ?: return true
}
}
return super.dispatchKeyEvent(event)
}
override fun requestChildFocus(child: View?, focused: View) {
mFocusView = focused
super.requestChildFocus(child, focused)
}
}