对话框 - 指定的子项已经有父项。您必须首先在子项的父项上调用removeView()。

25

在要求用户打开互联网服务并尝试点击按钮后,我的应用程序崩溃并显示错误消息。

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
在这一行它崩溃了,我已经尝试过这样做但完全没有解决。
if(alert.getContext() != null){
            alert.show();
        }

这是完整的代码

else if (id == R.id.xyz) {

            //startActivity(borrowIntent);
            AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
            alert.setTitle("xyz");
            input.setFilters(new InputFilter[] {
                    // Maximum 2 characters.
                    new InputFilter.LengthFilter(6),
                    // Digits only.
                    DigitsKeyListener.getInstance(), 
                });
            // Digits only & use numeric soft-keyboard.
            input.setKeyListener(DigitsKeyListener.getInstance());
            input.setHint("xyz");
            alert.setView(input);
            alert.setPositiveButton("Borrow", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                if(input.getText().length() == 0)
                {
                    input.setError("xyz is required !");
                }
                else
                {

                   if(isNetworkAvailable())
                      {
                         xyz( input.getText().toString());

                      }else{

                            //setContentView(R.layout.main);

                            AlertDialog.Builder builder = new AlertDialog.Builder(
                                    MainActivity.this);
                              builder.setCancelable(false);
                              builder.setTitle("xyz");
                              builder.setMessage("Please enable wifi services");
                              builder.setInverseBackgroundForced(true);
                              builder.setPositiveButton("Ok",
                                      new DialogInterface.OnClickListener() {
                                          @Override
                                          public void onClick(DialogInterface dialog,
                                                  int which) {

                                              startActivityForResult(new Intent(android.provider.Settings.ACTION_SETTINGS), 0);
                                              dialog.dismiss();


                                          }
                                      });
                              AlertDialog alerts = builder.create();
                              alerts.show();
                           }//end of block

                        }
              }
            });
            alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int whichButton) {
                // Canceled.
              }
            });
            if(alert.getContext() != null){
            alert.show(); //crashes at this line
            }
        }

请问我错过了什么?


你可以把使用该对话框的活动或片段代码粘贴在此吗? - mdDroid
6个回答

24
问题出在这行代码上: alert.setView(input); 你添加了已经有 parentinput View。 创建新的 input 实例。

1
我只需要在类级别声明的一个类型为EditText的输入实例。 - Blaze
以编程方式生成EditText(https://dev59.com/w2cs5IYBdhLWcg3wRB7h) - dieter_h
但是你必须检查视图是否为空或非空。 - Blaze

18

根据这个帖子,添加以下检查以从其父级中移除输入并重新添加:

if(input.getParent()!=null)
        ((ViewGroup)input.getParent()).removeView(input); // <- fix
    alert.addView(input);

3

请添加以下代码

 final AlertDialog alertd = alert.create();

之后

 AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);

输入实际上是一个文本框。因此,删除后用户将有一个输入数据的字段。 - Blaze
对话框可以在片段或活动中。 - mdDroid
输入是对EditText的引用 - Blaze
我必须修改我的代码。因为我找不到这段代码。 - Blaze
那么我现在将在哪里使用这个句柄 alerd 呢? - Blaze

1

以下情况也可能发生(我曾经遇到过):

有时,当您使用ListView初始化适配器时,该适配器属于特定布局。现在,假设此布局文件的根视图是具有id“root_view”的<LinearLayout>

如果您现在为活动注册上下文菜单,并创建一个AlerdDialog.Builder,选择某个菜单元素后出现它并将其初始化为具有名为“root_view”的id的根元素的布局文件,则所有属于AlertDialog的元素的子元素都会被“找不到”。您将无法使用findViewById访问这些元素,而只能从列表视图的<LinearLayout>访问这些元素,并且在调用builder.show()(或在这里的情况下为alert.show())的行处得到相同的错误消息。

因此,通常最好为布局文件中的元素命名唯一的ID,以供您的项目使用。


0

我忘记在 AlertDialog.Builder 上调用 create() 方法。当你在不调用 create() 方法的情况下调用 show() 方法时,AlertDialog 实例会被创建。这在第一次运行时可以正常工作,但随后的点击会导致 IllegalStateException 异常。由于我是在 onClickListener 中调用 show() 方法,每次单击按钮时都会创建一个新的 AlertDialog 实例。


0
在开头添加这行代码
View dialog_view= getLayoutInflater().inflate(R.layout.dialog_view, null);
TextInputEditText input = dialog_view.findViewById(R.id.input);

之前

AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);

那样可以创建一个新的输入实例并避免问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接