如何以编程方式将活动主题化为对话框?

时间:2016-03-07 00:42:13

标签: java android android-activity android-dialog

问题

如何以编程方式(不触及AndroidManifext.xml)设置Activity so that it looks like a dialog的主题?

注意:我可以修改AndroidManifext.xml,只要不需要修改它就可以在看起来像普通活动或对话框之间切换。

到目前为止我尝试了什么

我根据this stackoverflow answer尝试了以下内容:

public class DialogActivity extends Activity
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        setTheme(android.R.style.Theme_DeviceDefault_Dialog);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog);
        Log.d(TAG,"Build.VERSION.SDK_INT: "+Build.VERSION.SDK_INT); // 23
    }
}

但最终blacking out everything in the background

我也看到了this stackoverflow answer,并尝试了:

public class DialogActivity extends Activity
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        setTheme(android.R.style.Theme_DeviceDefault_Dialog);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog);
        getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
    }
}

但它最终会制作everything black

怎么办?谢谢。

4 个答案:

答案 0 :(得分:15)

背景

如果前景活动的主题根据其Activity是对话框,则会绘制Acivity后面的AndroidManifest.xml;否则android os将在其后面绘制Activity(可能是为了节省内存,因为它通常不会被看到)。

为了利用这一点,我们将Acitvity的主题设置为清单中的对话框,使得android os在其后面绘制Activity,但稍后,以编程方式设置我们的Activity我们在运行时喜欢的主题。

Example on github

I made an example and put it on github.

教程

第1步:styles.xml中为您的应用创建两个自定义主题。一个用于正常活动,另一个用于对话活动。自定义对话框主题从基础主题(也是对话框)继承非常重要。在我的例子中,父主题是Base.Theme.AppCompat.Light.Dialog.FixedSize)。这是我的styles.xml

<resources>

    <!-- custom normal activity theme -->    
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    </style>

    <!-- custom dialog activity theme -->
    <style name="AppTheme.Dialog" parent="Base.Theme.AppCompat.Light.Dialog.FixedSize">
        <!-- removing the dialog's action bar -->
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

</resources>
AndroidManifest.xml

第2步:,将相关Activity的主题设置为任何对话框主题。这使得android os认为Activity是一个对话框,所以它会在它后面绘制Activity,而不是将它黑掉。就我而言,我使用了Theme.AppCompat.Dialog。以下是我的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.eric.questiondialog_artifact">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name">
        <activity
            android:name=".DialogActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.Dialog"> <-- IMPORTANT!!! -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>
在实际活动中

第3步:,以编程方式将主题设置为正常活动的主题或对话框的主题。我的DialogActivity.java位于以下位置:

package com.example.eric.questiondialog_artifact;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

public class DialogActivity extends AppCompatActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        setTheme(R.style.AppTheme_Dialog); // can either use R.style.AppTheme_Dialog or R.style.AppTheme as deined in styles.xml
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dialog);
    }
}

答案 1 :(得分:1)

如果您正在寻找的只是一个具有透明背景的主题,请使用此功能:

<style name="Theme.Transparent" parent="android:Theme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>

将此样式应用于AndroidManifest文件中的活动,就是这样

答案 2 :(得分:0)

dailog.setMessage(...);

之前试用这些代码
Dialog id  = new AlertDialog.Builder(this,AlertDialog.THEME_DEVICE_DEFAULT_DARK);

Dialog ID = new AlertDialog.Builder(this,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);

//Default theme 
  

尝试使用旧主题      Dialog ID = new AlertDialog.Builder(this,AlertDialog.THEME_TRADITIONAL);

尝试使用KITKAT主题

Dialog ID = new AlertDialog.Builder(this,AlertDialog.THEME_DEVICE_DEFAULT_DARK); //Dark


Dialog ID = new AlertDialog.Builder(this,AlertDialog.THEME_HOLO_LIGHT);
  

请务实使用这些代码

Exmaple

    dialog = new AlertDialog.Builder(this);
            dialog = new AlertDialog.Builder(this,AlertDialog.THEME_DEVICE_DEFAULT_DARK);
            dialog.setTitle("HAI");
            dialog.setMessage("look");
            dialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
Toast toast= Toast.makeText(getApplicationContext(), "This is exmaple theme", Toast.LENGTH_LONG);

答案 3 :(得分:0)

我迟到了,但仍然为未来的用户 你需要在 setTheme() 之后调用下面的代码调用这个可以让这个后面的 Activity 再次被看到。一旦所有这些活动都被重新绘制

// setTheme()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
            Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions");
            getActivityOptions.setAccessible(true);
            Object options = getActivityOptions.invoke(activity);

            Class<?>[] classes = Activity.class.getDeclaredClasses();
            Class<?> translucentConversionListenerClazz = null;
            for (Class clazz : classes) {
                if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
                    translucentConversionListenerClazz = clazz;
                }
            }
            Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent",
                    translucentConversionListenerClazz, ActivityOptions.class);
            convertToTranslucent.setAccessible(true);
            convertToTranslucent.invoke(activity, null, options);
        } catch (Throwable t) {
        }
        } else {
            try {
            Class<?>[] classes = Activity.class.getDeclaredClasses();
            Class<?> translucentConversionListenerClazz = null;
            for (Class clazz : classes) {
                if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
                    translucentConversionListenerClazz = clazz;
                }
            }
            Method method = Activity.class.getDeclaredMethod("convertToTranslucent",
                    translucentConversionListenerClazz);
            method.setAccessible(true);
            method.invoke(activity, new Object[] {
                null
            });
        } catch (Throwable t) {
        }
        }