我有一个 ListView,里面有一些可聚焦的组件(主要是EditText
s)。是的,我知道这并不完全推荐,但总的来说,几乎一切都工作正常,并且焦点集中在它必须去的地方(我必须编码一些调整)。不管怎样,我的问题是,当用手指滚动列表然后突然使用轨迹球时,会出现奇怪的竞争条件当显示 IME 键盘时。某些东西必须越界并被回收,此时offsetRectBetweenParentAndChild()
方法必须启动并抛出IllegalArgumentException
.
问题是这个异常被抛出到任何我可以插入 try/catch 的块之外(据我所知)。因此,这个问题有两个有效的解决方案:
- 有人知道why抛出这个异常以及如何阻止它发生
- 有人知道如何在某个地方放置一个 try/catch 块,至少可以让我的应用程序生存。据我所知,问题在于焦点,所以它绝对不应该杀死我的应用程序(这就是它正在做的事情)。我尝试覆盖
ViewGroup
的方法,但是那两个offset*
方法被标记为最终的。
堆栈跟踪:
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): FATAL EXCEPTION: main
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): java.lang.IllegalArgumentException: parameter must be a descendant of this view
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.view.ViewGroup.offsetRectBetweenParentAndChild(ViewGroup.java:2633)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.view.ViewGroup.offsetDescendantRectToMyCoords(ViewGroup.java:2570)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.view.ViewRoot.scrollToRectOrFocus(ViewRoot.java:1624)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.view.ViewRoot.draw(ViewRoot.java:1357)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.view.ViewRoot.performTraversals(ViewRoot.java:1258)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.os.Handler.dispatchMessage(Handler.java:99)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.os.Looper.loop(Looper.java:130)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at android.app.ActivityThread.main(ActivityThread.java:3683)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at java.lang.reflect.Method.invokeNative(Native Method)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at java.lang.reflect.Method.invoke(Method.java:507)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
08-17 18:23:09.825: ERROR/AndroidRuntime(1608): at dalvik.system.NativeStart.main(Native Method)
While 布鲁斯的回答确实解决了问题,但它以一种非常残酷的方式做到了这一点,这损害了用户体验,因为一旦我们进行滚动,它就会清除每个视图的焦点。
它解决了问题的表象,但没有解决实际原因。
如何重现问题:
您的 EditText 具有焦点并且键盘已打开,然后您滚动直到 EditText 离开屏幕,并且它没有回收到现在显示的新 EditText。
我们先来了解一下为什么会出现这个问题:
众所周知,ListView 回收其视图并再次使用它们,但有时它不需要立即使用已离开屏幕的视图,因此它会保留它以供将来使用,并且因为它不需要再显示,所以它会保留它以供将来使用。将分离它,导致 view.mParent 为空。
然而键盘需要知道如何将输入传递给它,它通过选择聚焦视图(准确地说是 EditText)来实现。
所以问题是我们有一个具有焦点的 EditText,但突然没有父级,因此我们得到一个“参数必须是此视图的后代”错误。这是有道理的。
通过使用滚动侦听器,我们会造成更多问题。
解决方案:
我们需要监听一个事件,该事件会告诉我们视图何时进入侧堆并且不再附加,幸运的是 ListView 公开了此事件。
listView.setRecyclerListener(new AbsListView.RecyclerListener() {
@Override
public void onMovedToScrapHeap(View view) {
if ( view.hasFocus()){
view.clearFocus(); //we can put it inside the second if as well, but it makes sense to do it to all scraped views
//Optional: also hide keyboard in that case
if ( view instanceof EditText) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)