Android:如何创建一个没有标题的对话框?

276

我想在Android中生成一个自定义对话框。我是这样创建对话框的:

dialog = new Dialog(this);
dialog.setContentView(R.layout.my_dialog);

除了对话框的标题外,一切正常。即使我不设置对话框的标题,对话框弹出时在对话框位置有一个空白区域。

有没有办法隐藏对话框的这部分内容?

我尝试使用AlertDialog,但似乎布局未正确设置:

LayoutInflater inflater = 
    (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.map_dialog, null);

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(view);

// dialog = new Dialog(this);
// dialog.setContentView(R.layout.map_dialog);

dialog = builder.create();

((TextView) dialog.findViewById(R.id.nr)).setText(number);

如果我使用这段代码,最后一行会出现空指针异常。对话框不为null,因此我尝试检索的TextView不存在。
如果我取消注释使用Dialog构造函数那么所有正常工作,但是对话框布局上面的标题消失了。


7
@Janusz,请重新选择您对 https://dev59.com/_XE85IYBdhLWcg3wtV71#3407871 的答案。 - Pacerier
尝试使用https://dev59.com/Hm025IYBdhLWcg3wAxF9而不是以前的答案...简单明了。 - Mohammed mansoor
只需不调用AlertDialog.Builder.setTitle()方法,你的对话框就会出现没有标题的状态。 - marvatron
26个回答

587

在从头创建对话框时,可以使用FEATURE_NO_TITLE,如下所示:

Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
但是当创建AlertDialog(或使用Builder)时,它不起作用,因为它已经禁用了标题并在内部使用自定义标题。 我查看了SDK源代码,认为无法解决。所以,我认为唯一的解决办法是直接使用Dialog类从头开始创建自定义对话框。 此外,可以使用样式来实现这一点,例如在styles.xml中:
<style name="FullHeightDialog" parent="android:style/Theme.Dialog">
   <item name="android:windowNoTitle">true</item>
</style>

然后:

Dialog dialog = new Dialog(context, R.style.FullHeightDialog);

不必从头开始创建自定义对话框,我按照oliverg的建议创建了styles.xml。然后,在清单文件中的<activity>...</acitivity>声明中添加了android:theme="@style/FullHeightDialog"。它就奏效了。谢谢。 - Indrajeet
@olivierg 但我想要一个具有完整高度对话框的按钮。有什么解决方案吗? - Pacerier
1
注意:requestWindowFeature这一行必须在setContentView之前。 - Fattie
虽然这个回答最能解决实际问题,但我认为被采纳的回答提供的解决方案是最好的。一开始我是使用一个干净的Dialog来做的,但创建一个AlertDialog更容易。就像在文档中所述: Dialog类是对话框的基类,但你应该避免直接实例化Dialog。 相反地,请使用下列子类之一:<AlertDialog 和其他描述在此处>。 AlertDialog也处理生命周期和轻松的确定/取消操作。 - Krøllebølle

213

使用以下代码可以隐藏对话框的标题:

dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);


之前版本的答案有些复杂:

您需要使用 AlertDialog。Android开发者网站上有关于自定义对话框的详细解释。

简单来说,你可以使用下面从官方网站复制的代码来实现。这个代码会加载一个自定义布局文件,设置基本的文本和图标,然后创建对话框。最后使用 alertDialog.show() 来显示对话框。

AlertDialog.Builder builder;
AlertDialog alertDialog;

Context mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater)
        mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog,
        (ViewGroup) findViewById(R.id.layout_root));

TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);

builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
alertDialog = builder.create();

回应评论:

我假设带有id为nr的TextView存在于你用View view = inflater....充气的视图中。如果是这样的话,那么你只需要改变一点:将dialog.findView...改为view.findView...。然后在完成此操作后,请记住使用dialog.show(),甚至可以使用builder.show()而不必担心执行builder.create()


4
我认为您可能误读了问题?Janusz已经有了自定义对话框并只需要有关删除标题的信息。 - Donal Rafferty
17
根据官方文档,“使用基本Dialog类创建的对话框必须有一个标题。如果您不调用setTitle(),则用于标题的空间将保持为空白,但仍然可见。如果您根本不想要标题,则应使用AlertDialog类创建自定义对话框。”我个人没有亲自尝试过,但这意味着即使使用自定义对话框布局或主题,也无法删除标题空间。 - Steve Haley
2
重新考虑:我认为我们对“标题”有不同的理解。我认为他指的是弹出窗口顶部的空间,而不是应用程序顶部的标题。 - Steve Haley
11
@SteveHaley,可以使用以下代码隐藏它:dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); - Sami Eltamawy
1
确保在填充对话框视图之前执行dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)。 - Alexey Podlasov
显示剩余7条评论

67
在你的代码中添加这一行。
requestWindowFeature(Window.FEATURE_NO_TITLE);  

或者在 XML 中使用主题。

android:theme="@android:style/Theme.NoTitleBar"

使用XML实现更好,因为代码版本会创建然后移除标题栏,这是一种资源浪费。

好的尝试,但它不起作用。我收到以下错误信息:   android.view.WindowManager $ BadTokenException:无法添加窗口 - 如果我要显示对话框,则令牌null不属于应用程序。

将警告对话框类型更改为系统对话框(例如,TYPE_SYSTEM_OVERLAY),看看是否解决了您的问题。


61

使用方法:

Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 

这将从对话框窗口中移除任何标题栏。


2
我之后怎么把它带回来? - android developer

57

setcontentview之前使用以下代码:

    Dialog dialog = new Dialog(this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 
    dialog.setContentView(R.layout.custom_dialog);

注意: 你必须按照相同的顺序和行数编写代码。在setContentView语句之前必须先使用requestWindowFeature


当在Dialogfragment中使用时,这个解决方案对我来说更好,因为被接受的答案会在对话框框架和内部内容视图之间创建一个微小的垂直间隙。 - Sebastian Roth

38

您可以通过以下方式删除标题

dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);

dialog是我的对话框的名称。


29

如果你在代码中使用requestWindowFeature(Window.FEATURE_NO_TITLE);,请确保它位于dialog.setContentView();之前,否则会导致应用程序崩溃。


之前有点怀疑,不过还是试了一下,结果非常惊讶地发现它明显有效。因为在android.developer.com上明确指出自定义对话框必须要有一个标题。:P - richardlin

10

在您的Custom_Dialog.java类中添加requestWindowFeature(Window.FEATURE_NO_TITLE)

public class Custom_Dialog extends Dialog {

    protected Custom_Dialog(Context context, int theme) {
        super(context, theme);
        // TODO Auto-generated constructor stub
        requestWindowFeature(Window.FEATURE_NO_TITLE); //This line 
    }
}

这是唯一对我有效的方法...由于某种原因,所有其他建议都没有起作用。我唯一推荐的是将构造函数设为public,并提供另一个仅需要Context参数的对话框构造函数。 - Justin

10
我发现有三种方法可以做到这一点 > 1)使用requestWindowFeature
Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(dialog.getWindow().FEATURE_NO_TITLE); 

2) 使用样式(style.xml)

<style name="FullHeightDialog" parent="android:style/Theme.Dialog">
   <item name="android:windowNoTitle">true</item>
</style>

Dialog dialog = new Dialog(context, R.style.FullHeightDialog);

3)在AndroidManifest.xml中使用XML主题

 android:theme="@android:style/Theme.NoTitleBar"

1
方法一应该是dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); - Jon Willis

7
olivierg的答案对我有用,如果你想要创建自定义Dialog类,则是最佳解决方案。然而,我很困扰的是我不能使用AlertDialog类。我希望能够使用默认的系统AlertDialog样式。创建一个自定义对话框类将没有这个样式。
因此,我找到了一个解决方案(hack),可以在不创建自定义类的情况下工作,您可以使用现有的构建器。
AlertDialog将一个View放置在您的内容视图上方,作为标题的占位符。如果您找到该视图并将其高度设置为0,则该空间会消失。
我已经在2.3和3.0上测试过了,可能还不能在每个版本上工作。
以下是两个辅助方法:
/**
 * Show a Dialog with the extra title/top padding collapsed.
 * 
 * @param customView The custom view that you added to the dialog
 * @param dialog The dialog to display without top spacing
     * @param show Whether or not to call dialog.show() at the end.
 */
public static void showDialogWithNoTopSpace(final View customView, final Dialog dialog, boolean show) {
    // Now we setup a listener to detect as soon as the dialog has shown.
    customView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            // Check if your view has been laid out yet
            if (customView.getHeight() > 0) {
                // If it has been, we will search the view hierarchy for the view that is responsible for the extra space. 
                LinearLayout dialogLayout = findDialogLinearLayout(customView);
                if (dialogLayout == null) {
                    // Could find it. Unexpected.

                } else {
                    // Found it, now remove the height of the title area
                    View child = dialogLayout.getChildAt(0);
                    if (child != customView) {
                        // remove height
                        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
                        lp.height = 0;
                        child.setLayoutParams(lp);

                    } else {
                        // Could find it. Unexpected.
                    }
                }

                // Done with the listener
                customView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
         }

    });

    // Show the dialog
    if (show)
             dialog.show();
}

/**
 * Searches parents for a LinearLayout
 * 
 * @param view to search the search from
 * @return the first parent view that is a LinearLayout or null if none was found
 */
public static LinearLayout findDialogLinearLayout(View view) {
    ViewParent parent = (ViewParent) view.getParent();
    if (parent != null) {
        if (parent instanceof LinearLayout) {
            // Found it
            return (LinearLayout) parent;

        } else if (parent instanceof View) {
            // Keep looking
            return findDialogLinearLayout((View) parent);

        }
    }

    // Couldn't find it
    return null;
}

以下是一个使用示例:

这里是它的使用示例:

    Dialog dialog = new AlertDialog.Builder(this)
        .setView(yourCustomView)
        .create();

    showDialogWithNoTopSpace(yourCustomView, dialog, true);

如果您正在与DialogFragment一起使用,请重写DialogFragment的onCreateDialog方法。然后像上面的第一个示例一样创建并返回对话框。唯一的变化是,您应该将false作为第三个参数(show)传递,以便它不会在对话框上调用show()方法。DialogFragment稍后会处理它。
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new AlertDialog.Builder(getContext())
        .setView(yourCustomView)
        .create();

    showDialogWithNoTopSpace(yourCustomView, dialog, false);
    return dialog;
}

如果我进一步测试,我会确保更新任何需要的额外调整。


优雅的解决方案,加一。你知道如何在DialogFragment中使用它吗? - Binoy Babu
@Binoy 更新了 DialogFragments 的答案(这实际上是我个人使用的方式) - cottonBallPaws

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接