Search code examples
androidandroid-chips

How to fix ‘ChipGroup IllegalStateException’ error in android


I’m setting up a ChipGroup, and want to add chip when enter is clicked in my android application. How do I solve error IllegalStateException?

layout

<com.google.android.material.chip.ChipGroup
            android:id="@+id/chip_hashtag"
            android:text="Tag"
            android:layout_below="@+id/PlaceLayout"
            style="@style/Widget.MaterialComponents.Chip.Entry"
            android:layout_centerHorizontal="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:singleSelection="false"/>
        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/HashtagLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/chip_hashtag"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp">

            <EditText
                android:id="@+id/input_hashtag_advance"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="HashTag"
                android:inputType="text"
                android:nextFocusDown="@id/input_hashtag_advance"/>

        </com.google.android.material.textfield.TextInputLayout>

Code

input_hashtag_advance = view.findViewById(R.id.input_hashtag_advance);
        LayoutInflater inflater = LayoutInflater.from(getActivity());
        Chip chip_item = (Chip) inflater.inflate(R.layout.layout_chip, null, false);
        ChipGroup chip_hashtag = view.findViewById(R.id.chip_hashtag);

        input_hashtag_advance.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    switch (keyCode) {
                        case KeyEvent.KEYCODE_DPAD_CENTER:
                        case KeyEvent.KEYCODE_ENTER: {

                            chip_item.setText(input_hashtag_advance.getText().toString());

                            chip_hashtag.addView(chip_item);
                            input_hashtag_advance.setText(null);
                        }
                        return true;
                        default:
                            break;
                    }
                }
                return false;
            }
        });

        chip_item.setOnCloseIconClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                chip_hashtag.removeView(v);
            }
        });

I expect the to add chip when entered, but when second added I get an error.

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

on this line, I don't want to remove previously added chip

chip_hashtag.addView(chip_item);

Solution

  • According to Mike M

    Since that inflate() call is outside of the OnKeyListener, it only happens once, and chip_item always refers to that same first inflated Chip. After you add it the first time, it already has a parent, so the second attempt throws that Exception. Move that whole Chip chip_item = ... line into the OnKeyListener, right before the setText() call. You'll need to move the setOnCloseIconClickListener() call into there, too. Also, you could make just a single OnClickListener field for that, and set that one on all of the Chips, since you're removing the View v passed into it. – Mike M.

      input_hashtag_advance.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    switch (keyCode) {
                        case KeyEvent.KEYCODE_DPAD_CENTER:
                        case KeyEvent.KEYCODE_ENTER: {
                            LayoutInflater inflater = LayoutInflater.from(getActivity());
                            Chip chip_item = (Chip) inflater.inflate(R.layout.layout_chip, null, false);
                            ChipGroup chip_hashtag = view.findViewById(R.id.chip_hashtag);
                            chip_item.setText(input_hashtag_advance.getText().toString());
    
                            input_hashtag_advance.setText(null);
                            chip_item.setOnCloseIconClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    chip_hashtag.removeView(v);
                                }
                            });
                            chip_hashtag.addView(chip_item);
                        }
                        return true;
                        default:
                            break;
                    }
                }
                return false;
            }
        });