如何实现自定义AlertDialog视图

sto*_*986 105 android android-alertdialog

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

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

FrameLayout fl = (FrameLayout) findViewById(R.id.body);
fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
Run Code Online (Sandbox Code Playgroud)

首先,非常明显的是这add()是一个错字,并且意味着addView().

我对使用R.id.body的第一行感到困惑.它似乎是AlertDialog的body元素......但是我不能在我的代码中输入它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();
Run Code Online (Sandbox Code Playgroud)

小智 158

您可以直接从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"
              />
Run Code Online (Sandbox Code Playgroud)

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

LayoutInflater inflater = getLayoutInflater();
View dialoglayout = inflater.inflate(R.layout.dialog_layout, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialoglayout);
builder.show();
Run Code Online (Sandbox Code Playgroud)

  • @Temperage你最后添加了builder.show吗?我尝试了这段代码并且有效.我也传递null作为infalter.inflate的第二个参数 (7认同)
  • @AlexPretzlav:此示例中不需要dialog_layout_root.您只需要R.layout.[name_of_xml_file]的xml文件的名称. (5认同)
  • 在这个例子中R.id.dialog_layout_root在哪里?这不是当前活动中的一个视图吗? (4认同)
  • 这应该被选为最佳答案. (2认同)
  • 当自定义布局包含EditText时,这会产生ClassCastException,因为`getCurrentFocus()`将返回EditText,并且EditText无法转换为ViewGroup.使用`null`作为第二个参数可以解决这个问题. (2认同)

syn*_*nic 47

你是对的,这是因为你没有手动充气.看来你正试图从你的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));
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,body在android.R.id中没有被定义为常量.我还不清楚如何访问创建的AlertDialog的'body'元素.我仍然想知道如何做到这一点,但是现在我将尝试给视图充气并在构建器中使用setView. (16认同)
  • 抓住你膨胀的`View`.当你需要来自其内容的东西时,在`View`上调用`findViewById()`.请参阅:http://github.com/commonsguy/cw-android/tree/master/Database/Constants/ (5认同)
  • 实际上这仍然给我留下了一个问题(我是新手来扩大观点).使用`builder.setView(inflater.inflate(R.id.dialog,ROOT_VIEWGROUP [,ATTACH_TO_ROOT]))`,文档说根视图组是可选的.在这种情况下应该使用它吗?如果是这样......仍然需要弄清楚如何获得对AlertDialog的引用...... (2认同)
  • 它是可选的,但是你不会在你正在膨胀的布局中引用父级.像android:layout_gravity这样的东西在顶层视图上不起作用......也许你不需要它们.当您调用AlertDialog alert = builder.create()时,您可以引用AlertDialog.答案很短,它*是*可选的.尝试一下,取决于你在自定义布局中做了什么,它可能会起作用. (2认同)
  • 我不清楚如何在AlertDialog中引用*view*.如果我想引用父母,你会在这种情况下推荐做什么?我在alertDialog中看到的唯一返回视图的是getCurrentFocus() (2认同)

小智 19

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();
Run Code Online (Sandbox Code Playgroud)

作为参考,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>
Run Code Online (Sandbox Code Playgroud)


Dap*_*app 17

已编辑Android文档以更正错误.

调用AlertDialog中的视图 android.R.id.custom

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


Ser*_*des 12

这对我有用:

dialog.setView(dialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null));
Run Code Online (Sandbox Code Playgroud)


Sur*_*gch 12

自定义警报对话框

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

在此处输入图片说明

创建自定义布局

EditText这个简单示例使用了带有 的布局,但您可以将其替换为您喜欢的任何内容。

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>
Run Code Online (Sandbox Code Playgroud)

在代码中使用对话框

关键部分是

  • 使用setView指定的自定义布局到AlertDialog.Builder
  • 单击对话框按钮时,将任何数据发送回活动。

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

主活动.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();
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记

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

也可以看看

  • @philcruz,如果您升级到 Android Studio 3.0,则不再需要显式转换视图。IDE 可以推断类型。这是一个非常好的功能。它有助于清理代码很多。 (5认同)