Prevention / Trap "IllegalArgumentException error: parameter must be the stream of this view"

I have a ListView with some lumped components inside (basically EditText s). Yes, I know that this is not entirely recommended, but in general almost everything works fine, and the main attention is paid to where it should go (with some settings that I had to code). Anyway, my problem is that there is a strange race condition when scrolling the list with your finger, and then suddenly using the trackball when displaying the IME keyboard. Something must go beyond and be processed; at this moment, the offsetRectBetweenParentAndChild() method should kick and throw an IllegalArgumentException .

The problem is that this exception is thrown outside of any block into which I can insert try / catch (as far as I know). So, there are two correct solutions to this issue:

  • Someone knows why this exception is selected and how to stop it.
  • Someone know how to place a try / catch block somewhere, which at least will allow my application to survive. As far as I know, the problem is that the focus, so it definitely should not kill my application (this is what it does). I tried to override the ViewGroup methods, but these two offset* methods are marked as final.

Stack trace:

 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) 
+53
android illegalargumentexception viewgroup
Aug 17 '11 at 23:01
source share
15 answers

For what it's worth (or someone came across this), I abandoned the ListView approach for this action. Besides random crashes, it’s almost impossible to control focus correctly without setting windowSoftInputMode="adjustPan" , which opens up a bunch of other cans of worms. Instead, I just went for the “simple” ScrollView and worked just fine.

+10
Apr 24 2018-12-12T00:
source share

I'm sorry, I said that my previous answer is not the best way to solve this problem.

So I try this:
Add ScrollListener to your activity, when listView starts scrolling, clear current focus.

 protected class MyScrollListener 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(); } } } } 
+31
Oct. 15
source share

While Bruce's answer solves the problem, he does it very cruelly, which harms the UX, as it will clear the focus of each point of view as soon as we do the scroll.

It refers to the symptom of a problem, but does not solve the real cause.

How to reproduce the problem:

Your EditText has focus, and the keyboard opens, then scrolls until the EditText is disconnected from the screen and it has not been redesigned for the new EditText, which is now displayed.

Let me first understand why this problem occurs:

The ListView recycles its views and uses them again, as you all know, but sometimes it doesn’t need to use a view that immediately goes off the screen to save it for future use, and because it doesn’t need to be shown anymore, it will separate it , causing view.mParent to be null. however, the keyboard needs to know how to pass the input, and it does this by choosing the exact focused view or EditText.

Thus, the problem is that we have an EditText that has focus but suddenly does not have a parent, so we get the error "parameter must be a descendant of this view". has the meaning.

Using the scroll listener we cause more problems.

Decision:

We need to listen to an event that tells us when the view has moved to the heap and is no longer connected, fortunately ListView provides this event.

 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); } } } }); 
+28
Nov 17 '16 at 16:05
source share

try it

  @Override public View getView(int position, View convertView, ViewGroup parent) { //abandon current focus View currentFocus = ((Activity)mContext).getCurrentFocus(); if (currentFocus != null) { currentFocus.clearFocus(); } // other code } 

EDIT:

See also: Best Solution

+23
Oct. 15 '12 at 3:05
source share

I ran into the same problem and found out this solution - in OnGroupCollapseListener/OnGroupExpandListener and OnScrollListener for ExpandableListView I cleared focuse and hid the forced keyboard. Also do not forget to specify manifest for your activity windowSoftInputMode="adjustPan" :

  expListView.setOnGroupCollapseListener(new OnGroupCollapseListener() { @Override public void onGroupCollapse(int groupPosition) { InputMethodManager inputManager = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (getWindow().getCurrentFocus() != null) { inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); getCurrentFocus().clearFocus(); } } }); expListView.setOnGroupExpandListener(new OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { InputMethodManager inputManager = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (getWindow().getCurrentFocus() != null) { inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); getCurrentFocus().clearFocus(); } } }); expListView.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { InputMethodManager inputManager = (InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (getCurrentFocus() != null) { inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); getCurrentFocus().clearFocus(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {} }); 

I do not know exactly what OnGroupExpandListener is required or not, this can be useless.

+7
May 28 '14 at 8:53
source share

I used Bruce's answer with a slight adjustment.

I needed adjustResize in my activity instead of adjustpan , but when I tried it, an error occurred again.
I replaced ScrollView with <android.support.v4.widget.NestedScrollView , and now it works fine. Hope this helps someone!

+7
Oct 30 '16 at 11:07
source share

I ran into this problem and the validcat solution worked for me, but I had to call getWindow().getCurrentFocus().clearFocus() .

+3
Sep 08 '15 at 21:37
source share

I have the simplest but not a good solution. Just extend NestedScrollView and override the onSizeChanged method, add a try catch block.

 public class FixFocusErrorNestedScrollView extends NestedScrollView { public FixFocusErrorNestedScrollView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { try { super.onSizeChanged(w, h, oldw, oldh); } catch (Exception e) { e.printStackTrace(); } } } 

In my case, I have the view of the tow layer, the top layer is listView, the bottom is NestedScrollView. An error occurs when I switch a layer. The focus is on the ListeView item (button).

Therefore, I cannot make the button lose focus. Then the best solution is NestedScrollView.

+3
Aug 22 '18 at 9:11
source share

In the case of an extended list view, if your children have editing text, you need to change the focus before the descendants to view the extended list

 expandableListView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 
+2
Apr 10 '17 at 8:40
source share

I encountered the same problem when using EditText in Recyclerview . After a lot of struggle and trying different options, I found out that after deleting a line when the keyboard is open, this problem occurs. I decided to force it to close my keyboard and change notifyItemRemoved(position) with notifyDataSetChanged() .

+2
Feb 20 '18 at 11:45
source share

In my case, this was due to windowSoftInputMode="adjustPan" , listView and editText in the list item (view header).

To fix this, I call the hidden soft keyboard method until the action completes.

 public void hideKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); View focusView = activity.getCurrentFocus(); if (focusView != null) { inputMethodManager.hideSoftInputFromWindow(focusView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } 
+1
May 15 '15 at 8:51
source share

If none of the proposed solutions apply to you ...

I ran into a similar error and noticed that it was reported on my users' devices (after a crash) without any clear explanation of what caused it (the same as the log shown on the question) - more specifically, only a problem happened on Samsung Galaxy devices (including S6) (but not on Nexus devices or other devices, so my testing did not initially reveal a problem). So, firstly, it's worth checking if the problem is a specific device or not.

What I later discovered is that when you press the back button when the Samsung virtual keyboard is displayed in the text box, the application resets this error, but not always!

Indeed, the text field causing the crash was also displayed within the scrollview with fillViewPort = "true" enabled.

I found that removing the fillViewPort option from scrolling does not contradict the Samsung keyboard showing / hiding. I suspect that the problem is partially due to the fact that the Samsung keyboard is different virtual keyboards than the Nexus keyboard, so only a subset of my users experiences this problem, and it will be broken only on their devices.

As a rule, and if none of the other solutions offered here applies to you, I would check if the problem is device-specific, and also try to simplify the view that I am working on until I find the “culprit” "(component and the view, which I must add, was not reported in the crash logs - so I just stumbled upon a specific view, causing the problem by accident!).

Sorry, I can’t be more specific, but I hope that this will provide some guidance for further investigation if someone has a similar but unexplained problem.

+1
Jul 11 '16 at 19:58
source share

My answer is related to most of the answers here, but I just wanted to add that in my case, this failure occurred due to deleting the line with the edit text that currently had focus.

So, all I did was override the adapter removal method and asked if the deleted line contains the current focus editing, and if so, clear the focus.

This solved it for me.

0
Jul 11 '14 at 11:41
source share

Based on @Bruce's answer, you can resolve the error using recyclerview as follows:

 @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View currentFocus = ((Activity)context).getCurrentFocus(); if (currentFocus != null) { currentFocus.clearFocus(); } } 
0
Jun 22 '16 at 6:50
source share

I am using RecyclerView and none of the solutions presented worked. I got an error while deleting items.

Which made the work of overriding the adapter 'onItemDismiss (int position)' so that it first did "notifyDataSetChanged ()" before deleting the element, and then "notifyItemRemoved (position)" after deleting the element. Like this:

 // Adapter code @Override public void onItemDismiss(int position) { if (position >= 0 && getTheList() != null && getTheList().size() > position) { notifyDataSetChanged(); // <--- this fixed it. getTheList().remove(position); scrollToPosition(position); notifyItemRemoved(position); } } 

Also override "removeAt (int position)" in the TabFragment to trigger a new cleanup code, for example:

 // TabFragment code @Override public void removeAt(int position) { mAdapter.onItemDismiss(position); mAdapter.notifyItemRemoved(position); // <--- I put an extra notify here too } 
0
Dec 18 '16 at 19:40
source share



All Articles