如何实现自定义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中显示列表视图?