notifyItemRangeChanged() causing crash RecyclerView Android
Asked Answered
J

1

12

layout design:

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

Which will basically do a two way scroll. This UI is built for TV. The focused row in this grid will show extra detail and other rows wont. So whenever there is a focus change from one row to another in onFocusChange i modify the dataset of the Adapter and call notifyItemRangeChanged().

This works fine when the rows length exceeds that of the vertical length of the screen, i.e. vertically scrollable. The crash happens say like if there is less number of rows (like 4).

Error:

    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)

I tried calling notifydatasetchange, but that will return getAdapterPosition = -1 which will not result in focus change from 1 row to another

Since the Adapter code length exceeds character length set by stackoverflow i am providing drive link for the same. Adapter and viewholder layout code

No crash when scrolled vertically Items without crash

Crash on vertical scroll Items with crash

Johnathon answered 4/10, 2018 at 21:49 Comment(12)
can you post your code, adapter you are writtenCrucify
this link maybe help youCodie
thanks, have checked them, sadly not relevant to me.Johnathon
Can't really help with only the stacktrace attached to the question.Stoplight
@Stoplight I will add adapter code and viewholder layout code, will that do ?Johnathon
Try this: your_scrollview_object.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);Clack
@Ümañg ßürmån thanks, still same errorJohnathon
Can you please attach a screenshot for the issue. and I am more concerned for your comment "The crash happens say like if there is less number of rows (like 4)."-- Wanted to view the UI.Sears
@jiteshmohite please check added screenshotsJohnathon
@DJphy: Is recyclerView only contains four item inside second screenshot?Sears
@jiteshmohite yes, any number of rows less than the vertical length of the screen, when tried to scroll using focus it crashes, works fine if more number of items(rows) are presentJohnathon
@Johnathon I'm not sure if this will help, but you should bind the views in onBindViewHolder without delay because that's when the RecyclerView performs updates on its views afterwards. I suspect if you bind your views with Handler.postDelayed, then your binding may fail or encounter unexpected behavior. So try to remove the delay block, and you probably have to find another way to load your data asynchronously.Ain
S
2

I had the same issue when the items in the recyclerview are focusable. Try the following things:

Option 1 user windowSoftInputMode="adjustPan" in scrollview

Option 2 Append your custom ScrollListener to your Activity, the purpose is when RV start scrolling, clear current focus.

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();
                }
            }
        }

    }

Option 3:

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

there may be some other alternatives depending upon your code, you have to clear the focus.

Selfrighteous answered 31/10, 2018 at 18:19 Comment(3)
sure i will check this out, appreciate your helpJohnathon
Please let us know if it helped, else please share the concern, would try to figure out.Selfrighteous
tried your solution, didnt work, i cannot use option 2 since my platform is tv, here touch doesn't work, it works with remote control navigation. also i cannot clear focus in obindviewholder since i am registered to onfocuschangeJohnathon

© 2022 - 2024 — McMap. All rights reserved.