notifyItemRangeChanged()导致RecyclerView在Android上崩溃

12

布局设计:

HorizontalScrollView-parent, holding RV[
    RecyclerView=>(GridLayoutManager) (orientation verticle)]

这将基本上执行双向滚动。该用户界面适用于电视。此网格中的焦点行将显示额外的细节,而其他行则不会。因此,每当从onFocusChange中一行转换到另一行时,我会修改Adapterdataset并调用notifyItemRangeChanged()

当行数小于屏幕垂直长度(即可垂直滚动)时,这种方法可以正常工作。如果行数较少(如4行),就会发生崩溃。

错误:

    java.lang.IllegalArgumentException: parameter must be a descendant of this view
at android.view.ViewGroup.offsetRectBetweenParentAndChild(ViewGroup.java:5937)
at android.view.ViewGroup.offsetDescendantRectToMyCoords(ViewGroup.java:5866)
at android.widget.HorizontalScrollView.isWithinDeltaOfScreen(HorizontalScrollView.java:1168)
at android.widget.HorizontalScrollView.onSizeChanged(HorizontalScrollView.java:1569)
at android.view.View.sizeChange(View.java:19719)
at android.view.View.setFrame(View.java:19680)
at android.view.View.layout(View.java:19583)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1780)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1546)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1080)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:758)
at android.view.View.layout(View.java:19586)
at android.view.ViewGroup.layout(ViewGroup.java:6053)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2484)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2200)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1386)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6733)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)

我试过调用notifydatasetchange,但它会返回getAdapterPosition = -1,这将不会导致焦点从一行改变到另一行

由于适配器代码长度超过stackoverflow设置的字符长度,因此我提供了相应的驱动程序链接。 适配器和视图持有者布局代码

垂直滚动时无崩溃 未崩溃的项目

垂直滚动时崩溃 有崩溃的项目


这个链接可能会对您有所帮助:https://dev59.com/SYvda4cB1Zd3GeqPaILZ。 - sanemars
谢谢,我已经查看了它们,但很遗憾对我不相关。 - DJphy
仅凭附加在问题中的堆栈跟踪无法提供真正的帮助。 - hardartcore
尝试这样做:your_scrollview_object.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); - Ümañg ßürmån
@DJphy:第二张截图中recyclerView里只有四个项目吗? - Jitesh Mohite
显示剩余7条评论
1个回答

2

当recyclerview中的项目具有焦点时,我遇到了同样的问题。 请尝试以下方法:

选项1 在scrollview中使用 windowSoftInputMode="adjustPan"

选项2 将自定义ScrollListener添加到Activity中,目的是在RV开始滚动时清除当前焦点。

protected class FocusableScrollListner implements OnScrollListener {

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            // do nothing 
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (SCROLL_STATE_TOUCH_SCROLL == scrollState) {
                View currentFocus = getCurrentFocus();
                if (currentFocus != null) {
                    currentFocus.clearFocus();
                }
            }
        }

    }

选项三:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View currentFocus = ((Activity)context).getCurrentFocus();
    if (currentFocus != null) {
        currentFocus.clearFocus();
    }
}

根据您的代码,可能有其他选择可供选择,您需要清除焦点。


当然,我会检查这个的,感谢你的帮助。 - DJphy
请告诉我们是否有帮助,否则请分享您的疑虑,我们会尝试解决。 - aanshu
尝试了你的解决方案,但没有成功。我不能使用选项2,因为我的平台是电视。在这里,触摸无效,需要使用遥控器导航。此外,在我注册到onfocuschange之后,我无法清除obindviewholder中的焦点。 - DJphy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接