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

Posted

技术标签:

【中文标题】如何以编程方式将活动主题化为对话?【英文标题】:how to programatically theme an activity to be like a dialog? 【发布时间】:2016-06-20 10:57:41 【问题描述】:

问题

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

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

到目前为止我已经尝试过什么

我根据this *** 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 *** 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。

做什么?谢谢。

【问题讨论】:

可能重复:***.com/questions/1979369/…。可能你也对此感兴趣:github.com/pingpongboss/StandOut @NguyenDoanTung 谢谢。我也看到了那篇帖子,但大多数答案都涉及修改我不想做的AndroidManifest.xml。我尝试了***.com/a/22216966/2898715 中提到的第一种方法,但没有产生我问题中提到的令人满意的结果。另外,谢谢你的github链接,我检查了,但我真的希望有一个更简单的解决方案。 @Eric 惊人地解决了这个问题,谢谢,发送了赏金。必须在清单中设置 Theme.AppCompat.Dialog。您只能在 onCreate 中设置自己的样式。这也是我的问题的答案:***.com/a/67045156/294884 【参考方案1】:

背景

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

为了利用这一点,我们将 Acitvity 的主题设置为清单中的一个对话框,使 android 操作系统在其后面绘制 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操作系统认为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);
    

【讨论】:

您能否使用应用程序目标 API 27 及更高版本检查此解决方案。我在全屏主题 Only fullscreen activities can request orientation 上崩溃了。当我将全屏设置为默认设置并在运行时更改为对话框主题时。背景是黑色的。如果预设了对话框主题,则全屏崩溃 我刚刚在 Android Pie (API 28) 上测试了这个解决方案。当以编程方式将 Activity 作为全屏或对话框启动时,它似乎可以正常工作而不会崩溃。 你能在github上添加一个示例项目吗?谢谢 @NamTrung 嘿,我终于有时间创建an example for this answer。 如果想改变activity的大小,必须删除style中的.FixedSize,并更改LinearLayout的参数【参考方案2】:

如果您正在寻找的只是一个为您的活动提供透明背景的主题,请使用:

<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 文件中的活动,就是这样

【讨论】:

【参考方案3】:

我迟到了,但仍然为未来的用户 你需要在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) 
        
        

【讨论】:

【参考方案4】:

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);

【讨论】:

以上是关于如何以编程方式将活动主题化为对话?的主要内容,如果未能解决你的问题,请参考以下文章

PHP Drupal(6和7):以编程方式更改活动主题

Drupal(6&7):以编程方式更改活动主题

Android:如何创建透明的对话框主题活动

Jetpack Compose:如何以编程方式将主题从浅色模式更改为深色模式 onClick

活动(主题对话框)在其上的来电屏幕阻塞

如何在 Holo 主题 Api 11-17 Android 中以编程方式将 EditText 背景设置为默认值