Dialog skinning with AppCompat-v7 22 results in ugly shadows on api < 21

12,750

Solution 1

With the new AppCompat v22.1 you can use the new android.support.v7.app.AlertDialog or the new AppCompatDialog

Just use a code like this (of course in your case you have to use a custom layout to have the progress bar)

import android.support.v7.app.AlertDialog

AlertDialog.Builder builder =
       new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyle);
            builder.setTitle("Dialog");
            builder.setMessage("Lorem ipsum dolor ....");
            builder.setPositiveButton("OK", null);
            builder.setNegativeButton("Cancel", null);
            builder.show();

And use a style like this:

<style name="AppCompatAlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
        <item name="colorAccent">#FFCC00</item>
        <item name="android:textColorPrimary">#FFFFFF</item>
        <item name="android:background">#5fa3d0</item>
    </style>

Solution 2

In case anyone is still looking for a simple and effective solution, just add this line to your "alertDialog" style:

<item name="android:windowBackground">@android:color/transparent</item>

P.S. changing this property also affects PreferenceFragment's dialogs on API >= 21, so make sure you are using different styles: with transparent bg for API < 21, and without any changes for API >= 21

Solution 3

I had the exact same problem with the new AppCompat 22 library when using android.support.v7.app.AlertDialog for all my AlertDialogs, but the extra background layers only affected ProgressDialogs.

All my AlertDialogs when styled using my custom theme looked great, but the ProgressDialog's had the weird overlay on the background as described in the OP.

An option I had was to set a specific style each time I constructed a ProgressBar, but I was looking for an application wide solution.

With the help of these two links:

How to Style AlertDialogs like a Pro and Joerg Richter Blog I was able to get rid of the extra layer drawn on < 21 ProgressDialogs.

The issue I found was that on all versions the ProgressBar draws its background based on what is defined by default in "android:alertDialogStyle".

So to get rid of the extra layer, I had to define my own styles and set them for "android:alertDialogStyle". In doing so, I'm also overriding the default layouts applied to ProgressDialogs.

Here's my themes.xml:

<item name="android:alertDialogTheme">@style/MyAlertDialogTheme</item>
<item name="alertDialogTheme">@style/MyAlertDialogTheme</item>
<item name="android:alertDialogStyle">@style/MyAlertDialogStyles</item>

And my styles.xml:

<style name="MyAlertDialogTheme">
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
    <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
    <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
    <item name="android:background">@color/theme_alert_dialog_background</item>
    <item name="colorAccent">@color/theme_accent_1</item>
</style>

<style name="AlertDialog">
    <item name="android:fullDark">@android:color/transparent</item>
    <item name="android:topDark">@android:color/transparent</item>
    <item name="android:centerDark">@android:color/transparent</item>
    <item name="android:bottomDark">@android:color/transparent</item>
    <item name="android:fullBright">@android:color/transparent</item>
    <item name="android:topBright">@android:color/transparent</item>
    <item name="android:centerBright">@android:color/transparent</item>
    <item name="android:bottomBright">@android:color/transparent</item>
    <item name="android:bottomMedium">@android:color/transparent</item>
    <item name="android:centerMedium">@android:color/transparent</item>
</style>

Solution 4

ProgressDialog - Try for below android 5

dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);

or

dialog.getWindow().clearFlags(LayoutParams.FLAG_DIM_BEHIND);

Solution 5

You may download revision 22.1.0 (updated a few days ago) and use android.support.v7.app.AlertDialog

Share:
12,750
snowdragon
Author by

snowdragon

Computer Science student.

Updated on June 04, 2022

Comments

  • snowdragon
    snowdragon almost 2 years

    I'm using AppCompat to write a material design styled app. Since AppCompat does not affect dialogs, I'm skinning the dialogs as such:

    styles.xml:

    <style name="AppTheme.Base" parent="Theme.AppCompat">
        <!-- Set AppCompat’s color theming attrs -->
        <item name="colorPrimary">@color/green</item>
        <item name="colorPrimaryDark">@color/green_darker</item>
        <item name="colorAccent">@color/accent</item>
    
        <item name="android:alertDialogTheme">@style/alertDialog</item>
        <item name="android:dialogTheme">@style/alertDialog</item>
    </style>
    
    <style name="alertDialog" parent="Theme.AppCompat.Dialog">
        <item name="colorPrimary">@color/green</item>
        <item name="colorPrimaryDark">@color/green_darker</item>
        <item name="colorAccent">@color/accent</item>
    </style>
    

    I am gettings exactly what I wanted on android api >= 21, but on other devices I end up with a "box" around the dialogs.

    Is there a way to get rid of the "box" around the dialog and even get the colors and material theme applied on api < 21, preferably without any additional depencendies?

    App on Api < 21:

    App on API < 21

    App on API >= 21:

    App on API >= 21

    • Eugen Pechanec
      Eugen Pechanec about 9 years
      For skinning alert dialogs you need to use the android:Theme.DeviceDefault.Dialog.Alert (always native look) theme. Otherwise the background will be duplicated. On API 21 you see no difference but I suspect there will be overdraw. For skinning activities as dialogs use the android:Theme.DeviceDefault.Dialog (native look) or Theme.AppCompat.Dialog (material look) themes.
    • snowdragon
      snowdragon about 9 years
      android:Theme.DeviceDefault.Dialog is only available on API > 14. What do I use on API 11?
    • snowdragon
      snowdragon about 9 years
      Additionally this also overdraws the border on non lollipop apis. image
    • Eugen Pechanec
      Eugen Pechanec about 9 years
      Honestly nobody gives a damn about API 11, there are virtually no devices of API 11 in practical use. You might as well make your minSdk=14.
    • snowdragon
      snowdragon about 9 years
      Agreed, minSdk=11 is a pain to work with. Assuming I choose to go for minSdk=14, how would I go about fixing the overdraw? Replacing Theme.AppCompat.Dialog by android:Theme.DeviceDefault.Dialog.Alert results in a crash.
    • Eugen Pechanec
      Eugen Pechanec about 9 years
      Can you update your original question with the stack trace? Off the top of my head I've had crashes when I was using anything from TextAppearance.AppCompat.* in these dialogs. Depending on what the exception is, you might need to define custom text appearances.
    • snowdragon
      snowdragon about 9 years
      I uploaded the stacktrace when using android:Theme.DeviceDefault.Dialog.Alert here: gist.github.com/git-commit/8490793d3fef8e24bbaf Sadly the stacktrace is cut off by logcat.
    • Eugen Pechanec
      Eugen Pechanec about 9 years
      Yeah, what I said above. Text appearances that you use in these dialogs cannot inherit or be TextAppearance.AppCompat.*. Define custom text appearance styles and use those. Inherit @android:TextAppearance and customize textColor and textSize according to Material Design specs (text type Body 1) and you'll be fine.
    • Eugen Pechanec
      Eugen Pechanec about 9 years
    • snowdragon
      snowdragon about 9 years
      I have been playing around with the material-dialog library. I think I might stick with it, if the solution you pointed at doesn't work or results in strange code noone else can maintain.
    • Mygod
      Mygod over 8 years
  • Neige
    Neige almost 9 years
    Did you know how can we change only the Positive Button TextColor and BackgroundColor ?
  • Sdghasemi
    Sdghasemi almost 9 years
    @Neige Use builder.getButton(DialogInterface.BUTTON_POSITIVE).setTextCo‌​lor(Color.parseColor‌​("#FF0000")); or .setBackgroundColor() or ... the same way after builder.show();.
  • Matt Kranzler
    Matt Kranzler about 8 years
    This is the correct answer. Create a theme extending one of the app compat themes and override the window background as mentioned above. Apply the theme in the construction of the ProgressDialog and no more weird background.
  • Guilherme Torres Castro
    Guilherme Torres Castro almost 8 years
    And for ProgressDialog ?
  • CreateAHero
    CreateAHero over 7 years
    This is working for me. I had to create two folders (values, values-21). I implemented the solution in the folder values\styles.xml. Finally I got rid of the strange border. Perfect.
  • idunnololz
    idunnololz over 7 years
    Excellent solution. For clarification, use the style titled "AlertDialog" as the android:alertDialogStyle and put it in your default style.xml. I actually did not need to create another style in my v21 style.xml.