114

有关 AlertDialog 的 Android 文档中,它提供了以下说明和示例,用于在 AlertDialog 中设置自定义视图:

如果您想显示更复杂的视图,请查找名为“body”的 FrameLayout 并将您的视图添加到其中:

FrameLayout fl = (FrameLayout) findViewById(R.id.body);
fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));

首先,很明显这add()是一个错字,应该是addView().

我对使用 R.id.body 的第一行感到困惑。它似乎是 AlertDialog 的主体元素......但我不能只在我的代码 b/c 中输入它,它会产生编译错误。R.id.body 在哪里被定义或分配或其他什么?

这是我的代码。我尝试setView(findViewById(R.layout.whatever)在构建器上使用,但没有用。我假设是因为我没有手动充气?

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title")
    .setCancelable(false)
    .setPositiveButton("Go", new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int id) {
        EditText textBox = (EditText) findViewById(R.id.textbox);
        doStuff();
    }
});

FrameLayout f1 = (FrameLayout)findViewById(R.id.body /*CURRENTLY an ERROR*/);
f1.addView(findViewById(R.layout.dialog_view));

AlertDialog alert = builder.create();
alert.show();
4

11 回答 11

160

您可以直接从 Layout Inflater 创建您的视图,您只需要使用您的布局 XML 文件的名称和文件中布局的 ID。

您的 XML 文件应具有如下 ID:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/dialog_layout_root"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:padding="10dp"
              />

然后您可以使用以下代码在构建器上设置布局:

LayoutInflater inflater = getLayoutInflater();
View dialoglayout = inflater.inflate(R.layout.dialog_layout, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialoglayout);
builder.show();
于 2011-04-23T11:39:25.637 回答
50

你是对的,这是因为你没有手动充气。看来您正试图从 Activity 的布局中“提取”“body”id,但这是行不通的。

你可能想要这样的东西:

LayoutInflater inflater = getLayoutInflater();
FrameLayout f1 = (FrameLayout)alert.findViewById(android.R.id.body);
f1.addView(inflater.inflate(R.layout.dialog_view, f1, false));
于 2010-05-08T19:23:39.183 回答
22

android.R.id.custom 为我返回 null。我设法让它工作,以防有人遇到同样的问题,

AlertDialog.Builder builder = new AlertDialog.Builder(context)
            .setTitle("My title")
            .setMessage("Enter password");
final FrameLayout frameView = new FrameLayout(context);
builder.setView(frameView);

final AlertDialog alertDialog = builder.create();
LayoutInflater inflater = alertDialog.getLayoutInflater();
View dialoglayout = inflater.inflate(R.layout.simple_password, frameView);
alertDialog.show();

作为参考, R.layout.simple_password 是:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="match_parent">

<EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/password_edit_view"
        android:inputType="textPassword"/>
<CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/show_password"
        android:id="@+id/show_password_checkbox"
        android:layout_gravity="left|center_vertical"
        android:checked="false"/>

</LinearLayout>
于 2013-03-27T22:18:37.480 回答
17

android 文档已被编辑以纠正错误。

AlertDialog 内的视图被称为android.R.id.custom

http://developer.android.com/reference/android/app/AlertDialog.html

于 2012-05-17T16:50:48.497 回答
14

自定义警报对话框

这个完整的例子包括将数据传回活动。

在此处输入图像描述

创建自定义布局

EditText这个简单的例子使用了一个带有 an 的布局,但是你可以用任何你喜欢的东西来替换它。

custom_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:paddingLeft="20dp"
              android:paddingRight="20dp"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

在代码中使用对话框

关键部分是

  • 用于setView将自定义布局分配给AlertDialog.Builder
  • 单击对话框按钮时将任何数据发送回活动。

这是上图所示示例项目的完整代码:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void showAlertDialogButtonClicked(View view) {

        // create an alert builder
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Name");

        // set the custom layout
        final View customLayout = getLayoutInflater().inflate(R.layout.custom_layout, null);
        builder.setView(customLayout);

        // add a button
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // send data from the AlertDialog to the Activity
                EditText editText = customLayout.findViewById(R.id.editText);
                sendDialogDataToActivity(editText.getText().toString());
            }
        });

        // create and show the alert dialog
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    // do something with the data coming from the AlertDialog
    private void sendDialogDataToActivity(String data) {
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
    }
}

笔记

  • 如果您发现自己在多个地方使用它,那么请考虑按​​照文档DialogFragment中的说明创建一个子类。

也可以看看

于 2017-10-14T07:24:32.873 回答
12

这对我有用:

dialog.setView(dialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null));
于 2013-08-07T14:56:54.823 回答
4

对我有用的最简单的代码行如下:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(R.layout.layout_resource_id);
builder.show();

无论哪种类型的布局(LinearLayout、FrameLayout、RelativeLayout)都可以使用setView ,只是在外观和行为上有所不同。

于 2016-11-07T03:03:21.933 回答
3

最简单的方法是使用android.support.v7.app.AlertDialog而不是在 API 21android.app.AlertDialogpublic AlertDialog.Builder setView (int layoutResId)可以使用的地方。

new AlertDialog.Builder(getActivity())
    .setTitle(title)
    .setView(R.layout.dialog_basic)
    .setPositiveButton(android.R.string.ok,
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                //Do something
            }
        }
    )
    .setNegativeButton(android.R.string.cancel,
        new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                //Do something
            }
        }
    )
    .create();
于 2016-05-25T08:55:29.093 回答
2

AlertDialog.setView(View view)确实将给定的视图添加到R.id.custom FrameLayout. AlertController.setupView()以下是最终处理此问题的 Android 源代码片段(mView是赋予AlertDialog.setView方法的视图)。

...
FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.**custom**);
custom.addView(**mView**, new LayoutParams(FILL_PARENT, FILL_PARENT));
...
于 2015-03-02T01:48:57.183 回答
1

将 ID 更改为 android.R.id.custom 后,我需要添加以下内容以显示要显示的视图:

((View) f1.getParent()).setVisibility(View.VISIBLE);

但是,这会导致新视图在没有背景的大父视图中呈现,从而将对话框分为两部分(文本和按钮,新视图介于两者之间)。通过在消息旁边插入我的视图,我终于得到了我想要的效果:

LinearLayout f1 = (LinearLayout)findViewById(android.R.id.message).getParent().getParent();

我通过使用 View.getParent() 和 View.getChildAt(int) 探索视图树找到了这个解决方案。不过,两者都不是很高兴。这些都不在 Android 文档中,如果他们改变了 AlertDialog 的结构,这可能会中断。

于 2015-09-15T09:31:48.250 回答
1

这样做最有意义,代码量最少。

new AlertDialog.Builder(this).builder(this)
        .setTitle("Title")
        .setView(R.id.dialog_view)   //notice this setView was added
        .setCancelable(false)
        .setPositiveButton("Go", new DialogInterface.OnClickListener() {
            @Override 
            public void onClick(DialogInterface dialog, int id) {
                EditText textBox = (EditText) findViewById(R.id.textbox);
                doStuff();
            }
        }).show();

有关您可以设置的扩展列表,请开始.set在 Android Studio 中输入

于 2018-04-27T07:07:48.617 回答