Android开发中,有数据提交需求是必不可少的,但是当提交内容过长的时候就需要用到ScrollView/NestScrollView 来解决过长问题,此时就容易遇到焦点的问题
- EditText 滚动后焦点没有消失,导致页面有异常问题
- 有验证码倒计时,当倒计时View滚动出页面后,会因为读秒而自动滚动到视野内
解决这两个问题一般网上的代码是:
scrollView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
scrollView.setFocusable(true);
scrollView.setFocusableInTouchMode(true);
scrollView.setOnTouchListener((v, event) -> {
v.requestFocusFromTouch();
return false;
});
这样确实可以解决问题,但是我最近发现在鸿蒙系统上,当滚动Scrollview的时候,会有页面自动增加一个阴影层的问题
看了源码:
public final boolean requestFocusFromTouch() {
// Leave touch mode if we need to
if (isInTouchMode()) {
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot != null) {
viewRoot.ensureTouchMode(false);
}
}
return requestFocus(View.FOCUS_DOWN);
}
发现应该是viewRoot.ensureTouchMode(false);这行代码出了问题,而且是系统适配问题,那我们就换个思路,不让Scrollview去抢占焦点了,让持有焦点的View 去主动清除焦点
所以就可以有下面两个方案:
方案一:适用于页面上只有一个View影响焦点
scrollView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
scrollView.setFocusable(true);
scrollView.setFocusableInTouchMode(true);
scrollView.setOnTouchListener((v, event) -> {
xxx.clearFocus();
return false;
});
方案二:适用于页面上存在多个View影响焦点
scrollView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
scrollView.setFocusable(true);
scrollView.setFocusableInTouchMode(true);
scrollView.setOnTouchListener((v, event) -> {
View view = getWindow().getDecorView().findFocus();
if (view != null) {
view.clearFocus();
}
return false;
});