Android 如何实现自定义 AlertDialog 视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2795300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement a custom AlertDialog View
提问by stormin986
In the Android docs on AlertDialog, it gives the following instruction and example for setting a custom view in an AlertDialog:
在AlertDialog 上的Android 文档中,它提供了以下说明和示例,用于在 AlertDialog 中设置自定义视图:
If you want to display a more complex view, look up the FrameLayout called "body" and add your view to it:
如果要显示更复杂的视图,请查找名为“body”的 FrameLayout 并将您的视图添加到其中:
FrameLayout fl = (FrameLayout) findViewById(R.id.body);
fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
First off, it's pretty obvious that add()
is a typo and is meant to be addView()
.
首先,很明显这add()
是一个错字,并且应该是addView()
.
I'm confused by the first line using R.id.body. It seems that it's the body element of the AlertDialog ... but I can't just enter that in my code b/c it gives a compile error. Where does R.id.body get defined or assigned or whatever?
我对使用 R.id.body 的第一行感到困惑。似乎它是 AlertDialog 的 body 元素......但我不能只是在我的代码 b/c 中输入它,它会产生编译错误。R.id.body 在哪里定义或分配或其他什么?
Here's my code. I tried to use setView(findViewById(R.layout.whatever)
on the builder but it didn't work. I'm assuming because I didn't manually inflate it?
这是我的代码。我试图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();
采纳答案by synic
You are correct, it's because you didn't manually inflate it. It appears that you're trying to "extract" the "body" id from your Activity's layout, and that won't work.
你是对的,那是因为你没有手动给它充气。看来您正在尝试从 Activity 的布局中“提取”“主体”ID,但这是行不通的。
You probably want something like this:
你可能想要这样的东西:
LayoutInflater inflater = getLayoutInflater();
FrameLayout f1 = (FrameLayout)alert.findViewById(android.R.id.body);
f1.addView(inflater.inflate(R.layout.dialog_view, f1, false));
回答by Andrewx2
You can create your view directly from the Layout Inflater, you only need to use the name of your layout XML file and the ID of the layout in file.
你可以直接从 Layout Inflater 创建你的视图,你只需要使用你的布局 XML 文件的名称和文件中布局的 ID。
Your XML file should have an ID like this:
您的 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"
/>
And then you can set your layout on the builder with the following code:
然后您可以使用以下代码在构建器上设置布局:
LayoutInflater inflater = getLayoutInflater();
View dialoglayout = inflater.inflate(R.layout.dialog_layout, null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialoglayout);
builder.show();
回答by John Rellis
android.R.id.custom was returning null for me. I managed to get this to work in case anybody comes across the same issue,
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();
For reference, R.layout.simple_password is :
作为参考,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>
回答by Dapp
The android documents have been edited to correct the errors.
已编辑 android 文档以更正错误。
The view inside the AlertDialog is called android.R.id.custom
AlertDialog 中的视图被称为 android.R.id.custom
http://developer.android.com/reference/android/app/AlertDialog.html
http://developer.android.com/reference/android/app/AlertDialog.html
回答by Sergio Viudes
This worked for me:
这对我有用:
dialog.setView(dialog.getLayoutInflater().inflate(R.layout.custom_dialog_layout, null));
回答by Suragch
Custom AlertDialog
自定义警报对话框
This full example includes passing data back to the Activity.
这个完整示例包括将数据传递回活动。
Create a custom layout
创建自定义布局
A layout with an EditText
is used for this simple example, but you can replace it with anything you like.
EditText
这个简单示例使用了带有 的布局,但您可以将其替换为您喜欢的任何内容。
custom_layout.xml
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>
Use the dialog in code
在代码中使用对话框
The key parts are
关键部分是
- using
setView
to assign the custom layout to theAlertDialog.Builder
- sending any data back to the activity when a dialog button is clicked.
- 使用
setView
指定的自定义布局到AlertDialog.Builder
- 单击对话框按钮时,将任何数据发送回活动。
This is the full code from the example project shown in the image above:
这是上图所示示例项目的完整代码:
MainActivity.java
主活动.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();
}
}
Notes
笔记
- If you find yourself using this in multiple places, then consider making a
DialogFragment
subclass as is described in the documentation.
- 如果您发现自己在多个地方使用它,请考虑
DialogFragment
按照文档中的描述创建一个子类。
See also
也可以看看
回答by kenix
The simplest lines of code that works for me are are follows:
对我有用的最简单的代码行如下:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(R.layout.layout_resource_id);
builder.show();
Whatever the type of layout(LinearLayout, FrameLayout, RelativeLayout) will work by setView
and will just differ in the appearance and behavior.
无论哪种布局(LinearLayout、FrameLayout、RelativeLayout)都适用,setView
只是外观和行为有所不同。
回答by flanaras
The easiest way to do this is by using android.support.v7.app.AlertDialog
instead of android.app.AlertDialog
where public AlertDialog.Builder setView (int layoutResId)
can be used below API 21.
最简单的方法是使用android.support.v7.app.AlertDialog
而不是在 API 21android.app.AlertDialog
下public 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();
回答by Jung Soo Kim
AlertDialog.setView(View view)
does add the given view to the R.id.custom FrameLayout
. The following is a snippet of Android source code from AlertController.setupView()
which finally handles this (mView
is the view given to AlertDialog.setView
method).
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));
...
回答by Black Mantha
After changing the ID it android.R.id.custom, I needed to add the following to get the View to display:
将 ID 更改为 android.R.id.custom 后,我需要添加以下内容以使视图显示:
((View) f1.getParent()).setVisibility(View.VISIBLE);
However, this caused the new View to render in a big parent view with no background, breaking the dialog box in two parts (text and buttons, with the new View in between). I finally got the effect that I wanted by inserting my View next to the message:
然而,这导致新视图在没有背景的大父视图中呈现,将对话框分成两部分(文本和按钮,新视图介于两者之间)。通过在消息旁边插入我的视图,我终于得到了我想要的效果:
LinearLayout f1 = (LinearLayout)findViewById(android.R.id.message).getParent().getParent();
I found this solution by exploring the View tree with View.getParent() and View.getChildAt(int). Not really happy about either, though. None of this is in the Android docs and if they ever change the structure of the AlertDialog, this might break.
我通过使用 View.getParent() 和 View.getChildAt(int) 探索视图树找到了这个解决方案。不过,两者都不是很高兴。这些都不在 Android 文档中,如果他们改变了 AlertDialog 的结构,这可能会中断。