如何以编程方式将 activity 设置为像对话框一样的主题?
how to programatically theme an activity to be like a dialog?
问题
如何以编程方式(不触及 AndroidManifext.xml
)设置 Activity
so that it looks like a dialog 的主题?
注意:我可以修改 AndroidManifext.xml
,只要它不需要修改,以便在使其看起来像普通 activity 或对话框之间切换。
到目前为止我尝试了什么
我按照 this Whosebug 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 Whosebug 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.
做什么?谢谢。
背景
如果前景activity的主题根据其AndroidManifest.xml
是对话框,则在Acivity
后面绘制Activity
;否则 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>
第 2 步: 在 AndroidManifest.xml
中,将有问题的 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 步: 在实际 activity 中,以编程方式将主题设置为正常活动的主题或对话的主题。我的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);
}
}
如果您正在寻找的只是一个透明背景的主题activity,只需使用这个:
<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 文件中的 activity,就是这样
在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
Try this for Old 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);
Try these codes for Pragmatically
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);
我来晚了但还是为了以后的用户
你需要在 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) {
}
}
问题
如何以编程方式(不触及 AndroidManifext.xml
)设置 Activity
so that it looks like a dialog 的主题?
注意:我可以修改 AndroidManifext.xml
,只要它不需要修改,以便在使其看起来像普通 activity 或对话框之间切换。
到目前为止我尝试了什么
我按照 this Whosebug 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 Whosebug 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.
做什么?谢谢。
背景
如果前景activity的主题根据其AndroidManifest.xml
是对话框,则在Acivity
后面绘制Activity
;否则 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>
第 2 步: 在 AndroidManifest.xml
中,将有问题的 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 步: 在实际 activity 中,以编程方式将主题设置为正常活动的主题或对话的主题。我的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);
}
}
如果您正在寻找的只是一个透明背景的主题activity,只需使用这个:
<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 文件中的 activity,就是这样
在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
Try this for Old 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);
Try these codes for Pragmatically
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);
我来晚了但还是为了以后的用户
你需要在 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) {
}
}