Android:如何以编程方式将Activity的主题设置为Theme.Dialog

40
所以我有一个Activity(称为TestActivity),它需要作为普通的未主题化的Activity以及其他地方的Theme.Dialog。我试图重用同一个TestActivity来完成这两个任务。
我想要做的就是动态设置主题。 代码很简单: 这是我的Activity的onCreate,它使用黑色背景。
public void onCreate(Bundle icicle) {
    if (Utility.isDialog == true)
        setTheme(android.R.style.Theme_Dialog);
    super.onCreate(icicle);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
.....

这里是清单项。

<activity android:name=".TestActivity"/>

同时我找到了一篇帖子,说这是不可能完成的,帖子链接在这里http://code.google.com/p/android/issues/detail?id=4394。但是我有强烈的感觉这是可以完成的。

欢迎提出所有建议。


我应该接受这个问题 没有解决方案 这篇 帖子 上所说的吗? - 100rabh
9个回答

55

希望能提供一个解决此问题的方法。

问题: 如何同时将同一个Activity作为对话框和全屏显示。

解决方案 :

  1. 在AndroidManifest.xml中使用主题 @android:style/Theme.Dialog 定义你的Activity。
  2. 在相应的 .Java 文件中,检查定义了 dialog 模式的 intent 额外参数。
  3. 如果不存在,则将主题设置为 android.R.style.Theme。这是如果你没有定义任何主题时应用的默认主题。

代码 :

boolean fDialogMode = getIntent().hasExtra("dialog_mode");

if( ! fDialogMode ) {
    super.setTheme(android.R.style.Theme);
}

替代方案:

一个更加复杂的解决方案是使用下面的AlertDialog

  1. 定义一个继承自ArrayAdapterListAdapter类。
  2. getCount函数中返回1

@Override
public int getCount() { return 1; }
getView 函数中,inflate 所需的 activity 布局,并在返回 view 之前进行任何自定义。
@Override
public View getView( int position, View view, ViewGroup group ) {
    View v = view;
    if( v == null ) {
        v = getSystemService(Context.LAYOUT_INFLATER_SERVICE).inflate( <layout res id>, null );
    }

... Do any customization here    ....

      return v;
}

如果您在activity类中没有太多处理需求,那么这绝对是一种次选方案。唯一考虑使用此解决方案的原因可能是将其显示在对话框中的逻辑仅限于在对话框中使用它的地方。

这两个选项都适用于我,但出于显而易见的原因,我选择了第一个选项。 :-)


非常好的解释,谢谢!如果有人第一次看不懂(就像我一样:D)-先阅读@mozarty的解决方案,以了解应该在哪里放置这段代码。 - Dmitry Zaytsev

45

您可以在调用 setContentView(...)super.onCreate() 之前使用 setTheme(..),这样就可以正常工作了。


你没有调用 setContentView,但我知道它是可以做到的,因为我在我的活动中已经实现了。 - Ahmed Salem
4
把setTheme方法的调用放在super.onCreate之前,这样就能起作用了,谢谢! - Bradley Uffner
仅供参考:这个代码确实可以工作,但是由于某些原因,在创建新活动时它会造成巨大的延迟(在Kindle Fire上),并且会让我的应用程序在Nook Color上意外崩溃。 - Joris Weimar
我以前从未在Kindle上尝试过,谢谢提供信息,等我有了一个会测试一下。 - Ahmed Salem
这个解决方案并不适用于所有设备。考虑到Motorola Xoom,结果是一个对话框出现在黑色背景上,而不是透明的背景。 - Cookster
@user933237 这很有趣,我也发现你所描述的情况在 ACER iconia 平板电脑上也会出现。 - Ahmed Salem

11

和其他一些人一样,在onCreate中调用setTheme(在或之前我的super.onCreate调用)并没有起作用。但是,通过覆盖setTheme,我能够指定一个与Manifest.xml中声明的主题不同的主题。具体来说,以下内容可以正常工作:

@Override
public void setTheme(int resid) {
    boolean changeTheme = true;
    super.setTheme(changeTheme ? android.R.style.Theme_Dialog : resid);
}
我在讨论中找到了上述内容:https://code.google.com/p/android/issues/detail?id=4394

1
然而,在调用onCreate()之前调用setTheme(),在Android平台上就不能使用通常发送到activity的数据来决定是否更改主题。需要一些额外的技巧来做出这个决定。 - Steve B

10

2
鲁本虽然它可以正常工作(我之前也试过),但我看到的是黑色背景,而不是调用活动。 - 100rabh
那么你的主题属性不正确。你的android:windowBackground设置为什么了? - Reuben Scratton
Reuben,我还没有定义自定义样式。但是现在我将实现一个带有windowBackground到color/transparent的自定义样式。 - 100rabh
Reuben,即使自定义样式也无法正常工作。关于windowBackgound的答案,请参见此帖子https://dev59.com/P3I95IYBdhLWcg3wvgl9#2700683。 - 100rabh
1
请查看更新的帖子和代码。如需更多详细信息,请告知。 - 100rabh
在调用setContentView之后,是否可以调用setTheme,如果我再次调用setContentView(这次是在setTheme之后)?场景示例:用户看到活动,按下按钮,通过调用setTheme然后调用setContentView来更改主题。 - android developer

3
在调用 super.onCreate(savedInstance) 之前,请使用 setTheme 来设置主题。

0

默认主题库调用:

super.setTheme(android.R.style.Theme);

在我的情况下,我正在使用AppCompat主题,因此请确保在您的ID中引用正确的库(即:)。
super.setTheme(android.support.v7.appcompat.R.style.Theme_AppCompat_NoActionBar);

0

这可能不适用于您的情况,但您可以使用该主题:

Theme.Holo.DialogWhenLarge

当屏幕较大时,它会显示您的活动作为对话框,而在屏幕较小时则会显示为常规活动。 这在Android文档中Dialogs中有所涵盖,并包含有关编程对话框以及也可以作为全屏片段的信息。


-1

我知道我来晚了,但我想在这里发布一个解决方案:

请查看完整的源代码此处。这是我在更改主题时使用的代码...

SharedPreferences pref = PreferenceManager
       .getDefaultSharedPreferences(this);
String themeName = pref.getString("prefSyncFrequency3", "Theme1");
if (themeName.equals("Africa")) {
    setTheme(R.style.AppTheme);
} else if (themeName.equals("Colorful Beach")) {
    //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
    setTheme(R.style.beach);
} else if (themeName.equals("Abstract")) {
    //Toast.makeText(this, "set theme", Toast.LENGTH_SHORT).show();
    setTheme(R.style.abstract2);
} else if (themeName.equals("Default")) {
    setTheme(R.style.defaulttheme);
}

-1
setTheme(android.R.style.Theme_Dialog);

1
请花些时间解释一下这个解决方案是如何解决问题的,以便其他遇到类似问题的人可以清楚地了解该问题。 - Regolith

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