How does one programatically (without touching the AndroidManifext.xml
) set the theme of an Activity
so that it looks like a dialog?
Note: I am ok with modifying the AndroidManifext.xml
as long as it does not need to be modified in order to switch between making it look like a normal activity or a dialog.
I tried the following as per 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
}
}
But it ends up blacking out everything in the background.
I also saw this stackoverflow answer, and tried:
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));
}
}
but it ends up making everything black.
What do? Thank you.
The Activity
behind an Acivity
is drawn if the foreground activity's theme according to its AndroidManifest.xml
is a dialog; otherwise the android os will not draw the Activity
behind it (probably to save memory since it usually won't be seen anyway).
To exploit this, we set the theme of our Acitvity
to a dialog in the manifest, making the android os draw the Activity
behind it, but later, programatically set our Activity
's theme to whatever we like at runtime.
I made an example and put it on github.
Step 1: create two custom themes for your application in styles.xml
. One for normal activities, and another for dialog activities. It is important for the custom dialog theme to inherit from a base theme that is also a dialog. In my case, the parent theme is Base.Theme.AppCompat.Light.Dialog.FixedSize
). Here is my 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>
Step 2: in the AndroidManifest.xml
, set the theme of the Activity
in question to any dialog theme. This makes the android os think that the Activity
is a dialog, so it will draw the Activity
behind it, and not black it out. In my case, I used Theme.AppCompat.Dialog
. Below is my 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>
Step 3: in the actual activity, set the theme programatically to either the theme for normal activities, or the theme for dialogs. My DialogActivity.java
is below:
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);
}
}