首页 > 解决方案 > Is it impossible to dynamically add custom layouts using addView()?

问题描述

I am making a window to open a dialog window and write a comment.

When you open the dialog window, there is a layout where you can enter your first comment.

Comment can only be written in one line and the following comment layout is created by pressing EnterKey in the input field.

I originally implemented this as a RecyclerView, but now I am trying other methods as well. (using addView())

But when I used addView() I got the following error.

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

The solution to this is shown in the here. (And I would appreciate it if you could explain why this error occurs.)

There is no error when using this. However, no more items are added.

There is only the first item that existed when the dialog box was opened, and there is no response when pressing the Enter key.

I want to add items dynamically in real time.

What should I do?


fragment_wc_dialog.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".fragment.WritingCommentDialogFragment">
</LinearLayout>

wc_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context=".fragment.WritingCommentDialogFragment">

    <EditText
        android:id="@+id/comment_edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:gravity="center_vertical"
        android:drawableLeft="@drawable/ic_bullet_point"
        android:drawablePadding="5dp"
        android:layout_marginHorizontal="10dp"
        android:background="@null"
        android:textSize="15sp"
        android:inputType="text"
        android:maxLines="1"
        android:maxLength="22"
        android:imeOptions="actionNone"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

WCDialogFragment.java

public class WritingCommentDialogFragment extends DialogFragment {
    LinearLayout mContainer; // input layout
    View inputView;
    EditText editText;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_writing_comment_dialog, container, false);

        initViews(view);

        mContainer.addView(inputView); // The first item to be present when the dialog is opened

        editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if(event.getAction() == KeyEvent.ACTION_DOWN) {
                    mContainer.addView(inputView);
                }
                return true;
            }
        });

        return view;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.setCanceledOnTouchOutside(false);
        return dialog;
    }

    @Override
    public void onResume() {
        super.onResume();
        Toast.makeText(getContext(), "onResume()", Toast.LENGTH_SHORT).show();
        setDialogSize();
    }

    private void initViews(View view) {
        mContainer = view.findViewById(R.id.container);
        inputView = LayoutInflater.from(getContext()).inflate(R.layout.writing_comment_item, null);
        editText = inputView.findViewById(R.id.comment_edit);
    }
}

ADDED

enter image description here

标签: androiddialogfragment

解决方案


Your problem and the linked issue are different, as far as I can tell. The link has two views that they want to swap back and forth between, so the answer is to remove one view before adding the second. You want to build up a list of views, so you must use different instances rather than adding the same view over and over.

If you want the newly-added view to also respond to the Enter key, you can set the same listener to the new view too:

if(event.getAction() == KeyEvent.ACTION_DOWN) {
    EditText addedView = (EditText) LayoutInflater.from(getContext()).inflate(R.layout.writing_comment_item, mContainer, false);
    addedView.setOnEditorActionListener(this);
    mContainer.addView(addedView);
}

推荐阅读