英文:
Error while inflating a DialogFragment : The specified child already has a parent. You must call removeView() on the child's parent first
问题
在尝试展示包含RecyclerView的FragmentDialog时,我遇到了以下错误:“指定的子视图已经有一个父级。您必须先在子视图的父级上调用removeView()。”
以下是来自我的DialogFragment的代码:
public class MyDialogFragment extends AppCompatDialogFragment {
// ...(你的代码在这里)
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
// ...(你的代码在这里)
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
View recyclerViewContainer = createRecyclerView(mArrayListData); // 创建RecyclerView的视图
builder.setView(recyclerViewContainer)
.setTitle(requireContext().getString(R.string.title))
.setPositiveButton(requireContext().getString(R.string.ok_button), null);
Dialog dialog = builder.create();
// 显示Dialog并做一些设置
dialog.show();
Objects.requireNonNull(dialog.getWindow()).clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
// ...(你的代码在这里)
}
在这段代码中,createRecyclerView()
方法返回的是RecyclerView的视图,然后将该视图添加到AlertDialog.Builder
中。
请注意,如果您的代码中存在其它错误或问题,我并未在这里进行详细的检查。如果您的代码在这段被翻译的部分之外还有问题,请您进行调试和修复。
英文:
While trying to inflate a FragmentDialog containing a RecyclerView, I'm having this "The specified child already has a parent. You must call removeView() on the child's parent first." error.
Here's the code from my DialogFragment:
public class MyDialogFragment extends AppCompatDialogFragment {
private static final String DATA = "data";
private MyDialogFragment.MyDialogFragmentListener listener;
private ArrayList<MyArrayList> mArrayListData;
public static MyDialogFragment newInstance(ArrayList<MyArrayList> ArrayListData) {
Bundle args = new Bundle();
MyDialogFragment fragment = new MyDialogFragment();
args.putParcelableArrayList(DATA, ArrayListData);
fragment.setArguments(args);
return fragment;
}
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
if (getArguments() != null) {
mArrayListData = getArguments().getParcelableArrayList(DATA);
}
AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
builder.setView(createRecyclerView(mArrayListData))
.setTitle(requireContext().getString(R.string.title))
.setPositiveButton(requireContext().getString(R.string.ok_button), null);
Dialog dialog = builder.create();
/* Option set cause key board doesn't appear */
dialog.show();
Objects.requireNonNull(dialog.getWindow()).clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
dialog.setCanceledOnTouchOutside(false);
return dialog;
}
@Override
public void onResume() {
super.onResume();
final AlertDialog MyAlertDialog = (AlertDialog) getDialog();
if (MyAlertDialog != null) {
Button positiveButton = MyAlertDialog.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
...
dismiss();
}
});
}
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
listener = (MyDialogFragment.MyDialogFragmentListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() +
"must implement ExampleDialogListener");
}
}
public interface MyDialogFragmentListener {
void MyDialogFragmentListenerReturn(ArrayList<MyArrayList> ArrayListData);
}
private RecyclerView createRecyclerView(final ArrayList<MyArrayList> ArrayListData){
LayoutInflater inflater = requireActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.fragmentLayout, null, false);
RecyclerView MyRecyclerView = view.findViewById(R.id.recyclerViewId);
MyRecyclerAdapter myAdapter = new MyRecyclerAdapter (getActivity(), ArrayListData);
MyRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
MyRecyclerView.setAdapter(myAdapter);
myAdapter.setOnItemClickListener(new MyRecyclerAdapter.OnItemClickListener() {
@Override
public void onReturnValue(int position, int value) {
mArrayListData.get(position).setValue(value);
}
});
return MyRecyclerView;
}
}
My recycler adapter:
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.InsideRecyclerHolder> {
private final Context mContext;
private ArrayList<MyArrayList> mArrayListData;
private MyRecyclerAdapter.OnItemClickListener mListener;
MyRecyclerAdapter(Context context, ArrayList<MyArrayList> ArrayListData) {
mContext = context;
mArrayListData = RecyclerCarUpdateList;
}
@NonNull
@Override
public MyRecyclerAdapter.InsideRecyclerHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater myInflater = LayoutInflater.from(mContext);
View myOwnView = myInflater.inflate(R.layout.layout_recycler, parent, false);
return new MyRecyclerAdapter.InsideRecyclerHolder(myOwnView, mListener);
}
@Override
public void onBindViewHolder(@NonNull MyRecyclerAdapter.InsideRecyclerHolder holder, int position) {
MyArrayList currentItem = mArrayListData.get(position);
holder.t1.setText(currentItem.getFirstValue());
holder.e1.setHint(currentItem.getSecondValue());
}
@Override
public int getItemCount() {
return mArrayListData.size();
}
public interface OnItemClickListener {
void onReturnValue(int position, int newValue);
}
public void setOnItemClickListener(MyRecyclerAdapter.OnItemClickListener listener) {
mListener = listener;
}
static class InsideRecyclerHolder extends RecyclerView.ViewHolder {
final TextView t1;
final EditText e1;
InsideRecyclerHolder(@NonNull View itemView, final OnItemClickListener mListener) {
super(itemView);
t1 = itemView.findViewById(R.id.textValue);
e1 = itemView.findViewById(R.id.editTextValue);
e1.setImeOptions(EditorInfo.IME_ACTION_DONE);
e1.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mListener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
if (!e1.getText().toString().isEmpty()) {
listener.onReturnValue(position, Integer.parseInt(e1.getText().toString()))
}
}
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
}
}
And here's the stack:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:4915)
at android.view.ViewGroup.addView(ViewGroup.java:4746)
at android.view.ViewGroup.addView(ViewGroup.java:4718)
at androidx.appcompat.app.AlertController.setupCustomContent(AlertController.java:657)
at androidx.appcompat.app.AlertController.setupView(AlertController.java:475)
at androidx.appcompat.app.AlertController.installContent(AlertController.java:233)
at androidx.appcompat.app.AlertDialog.onCreate(AlertDialog.java:279)
at android.app.Dialog.dispatchOnCreate(Dialog.java:403)
at android.app.Dialog.show(Dialog.java:302)
at com.myself.myapp.MyDialogFragment.onCreateDialog(MyDialogFragment.java:61)
at androidx.fragment.app.DialogFragment.onGetLayoutInflater(DialogFragment.java:419)
at androidx.fragment.app.Fragment.performGetLayoutInflater(Fragment.java:1484)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:169)
at android.app.ActivityThread.main(ActivityThread.java:6578)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
It points the issue to the "dialog.show();" of my DialogFragment. I have to admit that I'm quite lost whit is. I have another DialogFragment that works the same way with no issue.
答案1
得分: 0
我解决了我的问题,最初我以为是我的Java代码出了问题,但实际上是XML布局出了问题...
我的DialogFragment布局是这样的:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FF8200"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MyDialogFragment ">
<TextView
android:id="@+id/textViewId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewId"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewId" />
</androidx.constraintlayout.widget.ConstraintLayout>
我只需要将RecyclerView作为布局的唯一元素:
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recyclerViewId"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="#FF8200"
android:nestedScrollingEnabled="false"
android:padding="16dp"
tools:context=".MyDialogFragment "
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
英文:
I solved my issue, I originaly thought it came from my java code but it was an xml layout issue ...
My DialogFrament layout was like that:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FF8200"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MyDialogFragment ">
<TextView
android:id="@+id/textViewId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewId"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewId" />
</androidx.constraintlayout.widget.ConstraintLayout>
and I just needed to use the RecyclerView as a sole element of the layout:
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recyclerViewId"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="#FF8200"
android:nestedScrollingEnabled="false"
android:padding="16dp"
tools:context=".MyDialogFragment "
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论