Preventing/catching “IllegalArgumentException: parameter must be a descendant of this view” error

后端 未结 15 1477
北恋
北恋 2020-11-27 13:46

I have a ListView with some focusable components inside (mostly EditTexts). Yeah, I know this isn\'t exactly recommended, but in general, almost everything is w

相关标签:
15条回答
  • 2020-11-27 14:01

    I used bruce's answer with a slight adjustment.

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

    0 讨论(0)
  • 2020-11-27 14:01

    I faced that problem, too, and the solution by validcat worked for me, but I had to call getWindow().getCurrentFocus().clearFocus().

    0 讨论(0)
  • 2020-11-27 14:03

    In my case it was related to windowSoftInputMode="adjustPan", listView and editText on list element (header view).

    In order to fix that I call hide soft keyboard method before activity is finished.

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-27 14:07

    Based on @Bruce answer, can resolve error with recyclerview like this:

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
            View currentFocus = ((Activity)context).getCurrentFocus();
            if (currentFocus != null) {
                currentFocus.clearFocus();
            }
    }
    
    0 讨论(0)
  • 2020-11-27 14:08

    While Bruce's answer does solve the problem, it does it in a very brutal way which harms the UX, as it will clear the focus of every view once we did a scroll.

    It deals with the symptom of the problem but it does not solve the actual cause.

    how to reproduce the problem:

    Your EditText has focus and the keyboard is opened, you then scroll till the point the EditText is off the screen, and it wasn't recycled to a new EditText that is now shown.

    Let's first understand why this problem happens:

    ListView recycles its views and uses them again as you all know, but sometimes it does not need to use a view that has gone off the screen immediately so it keeps it for future use, and because it doesn't need to be shown anymore it will detach it causing that view.mParent to be null. however the keyboard needs to know how to pass the input to, and it does it by choosing the focused view, or EditText to be precise.

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

    By using the scroll listener we are causing more problems.

    The Solution:

    We need to listen to an event which will tell us when a view has gone to the side heap and is no longer attached, luckily ListView exposes 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);
                    }
                }
            }
        });
    
    0 讨论(0)
  • 2020-11-27 14:08

    try this

     @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: Better Solution

    0 讨论(0)
提交回复
热议问题