常见默认获取焦点的组件: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)
}
}