Android focusableInTouchMode需要触犯两次才能点击
在Android开发中,有时我们会遇到一个奇怪的问题,就是当一个View设置了focusableInTouchMode
属性为true
后,需要点击两次才能获取焦点。这种情况下,一般来说,我们期望只需要点击一次就能获取焦点。那么,为什么会出现这种情况呢?本文将详细介绍这个问题的原因和解决方法,并提供相应的代码示例。
问题的原因
在Android中,当一个View设置了focusableInTouchMode
属性为true
后,这个View可以在触摸模式下获取焦点。但是,为什么会出现需要点击两次才能获取焦点的情况呢?
这是因为,当我们点击一个View时,系统会根据点击位置判断是否需要将焦点给这个View,如果需要将焦点给这个View,那么就会调用这个View的onTouchEvent
方法来处理触摸事件。而在onTouchEvent
方法中,会根据一些条件判断是否需要将焦点给这个View。其中,有一个关键条件是:在ACTION_DOWN
事件中,如果这个View是可以获取焦点的,并且这个View没有获取到焦点时,那么就会将焦点给这个View,并返回true
,表示事件已处理。而在ACTION_UP
事件中,如果这个View已经获取到焦点,那么就会处理点击事件。
所以,当一个View设置了focusableInTouchMode
属性为true
时,在ACTION_DOWN
事件中,这个View会获取到焦点,但是在ACTION_UP
事件中,由于这个View已经获取到焦点了,所以就不会处理点击事件,这就导致了需要点击两次才能获取焦点的问题。
解决方法
要解决这个问题,我们可以使用以下两种方法:
- 在
ACTION_DOWN
事件中,将焦点给其他的View,然后在ACTION_UP
事件中再将焦点还给目标View。这样,由于目标View在ACTION_UP
事件中没有焦点,所以会处理点击事件。示例代码如下:
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 将焦点给其他的View
otherView.requestFocus();
break;
case MotionEvent.ACTION_UP:
// 将焦点还给目标View
view.requestFocus();
break;
}
return true;
}
});
- 在
ACTION_DOWN
事件中,将目标View设置为不可获取焦点,然后在ACTION_UP
事件中再将其设置为可获取焦点。这样,在ACTION_UP
事件中,如果这个View已经获取到焦点,那么就会处理点击事件。示例代码如下:
view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 将View设置为不可获取焦点
view.setFocusableInTouchMode(false);
break;
case MotionEvent.ACTION_UP:
// 将View设置为可获取焦点
view.setFocusableInTouchMode(true);
break;
}
return true;
}
});
结语
在Android开发中,当一个View设置了focusableInTouchMode
属性为true
后,需要点击两次才能获取焦点的问题是比较常见的。通过本文的介绍,我们了解到这个问题的原因是因为在ACTION_DOWN
事件中,这个View会获取到焦点,但是在ACTION_UP
事件中,已经获取到焦点的View不会处理点击事件。为了解决这个问题,我们可以使用两种方法:在ACTION_DOWN
事件中,将焦点给其他的View,然后在ACTION_UP
事件中再将焦点还给目标View;或者在ACTION_DOWN
事件中,将目标View设置为不可获取焦点,然后在ACTION_UP
事件中再将其设置为可获取焦点。