如何实现自定义AlertDialog视图

在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中input,它会给编译错误。 R.id.body在哪里被定义或分配?

这是我的代码。 我试图在构build器上使用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(); 

你是正确的,这是因为你没有手动充气。 看起来你试图从你的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)); 

您可以直接从Layout Inflater创build视图,只需要使用布局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" /> 

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

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

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> 

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

AlertDialog中的视图称为android.R.id.custom

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

这对我工作:

 dialog.setView(dialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null)); 

最适合我的最简单的代码是:

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

无论什么types的布局(LinearLayout,FrameLayout,RelativeLayout)将通过setView工作, setView在外观和行为上有所不同。

AlertDialog.setView(View视图)确实将给定的视图添加到R.id. 自定义 FrameLayout。 以下是来自AlertController.setupView()的Android源代码片段,它最终处理了这个(mView是给AlertDialog.setView方法的视图)。

 ... FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.**custom**); custom.addView(**mView**, new LayoutParams(FILL_PARENT, FILL_PARENT)); ... 

最简单的方法是使用android.support.v7.app.AlertDialog代替android.app.AlertDialog ,其中public AlertDialog.Builder setView (int layoutResId)可以在API 21之下使用。

 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(); 

更改ID后android.R.id.custom,我需要添加以下来获取视图显示:

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

但是,这导致新的View在没有背景的大的父视图中呈现,将对话框分为两部分(文本和button,以及新的View之间的视图)。 我终于通过在消息旁边插入View来获得我想要的效果:

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

我通过View.getParent()和View.getChildAt(int)探索View树,find了这个解决scheme。 不过也不是真的很开心。 这些都不在Android文档中,如果他们改变AlertDialog的结构,这可能会中断。

自定义AlertDialog

这个完整的例子包括将数据传回给Activity。

在这里输入图像描述

创build一个自定义布局

带有EditText的布局用于这个简单的例子,但是你可以用你喜欢的任何东西replace它。

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
  • 当点击一个对话框button时,将任何数据发送回活动。

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

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子类,如文档中所述。

也可以看看

  • 带有一个,两个和三个button的Android警报对话框
  • 如何在Android Alert Dialog中显示列表视图?