Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace Button Background of Android DialogFragment

So I previously solved this problem thanks to the help of another thread, but due to some new changes to my app the previous solution no longer works. Here's the previous thread: Android App: Replace default button background with custom background in a Dialog Fragment

I'm trying to style the background drawables of the positive/negative buttons of a custom DialogFragment, and cannot seem to get any change to stick. Originally, I used the following:

@Override
public void onStart() {
    super.onStart();
    Button pButton =  ((AlertDialog) getDialog()).getButton(DialogInterface.BUTTON_POSITIVE);
    Button nButton =  ((AlertDialog) getDialog()).getButton(DialogInterface.BUTTON_NEGATIVE);

    pButton.setBackground(getResources().getDrawable(R.drawable.button_custom));
    nButton.setBackground(getResources().getDrawable(R.drawable.button_custom));
}

This worked beautifully and did exactly what I wanted. However, I think that this stopped working because I recently added a style created by the Android Action Bar Style generator found here: http://jgilfelt.github.io/android-actionbarstylegenerator

I've tried adding my styles to the style file generated by the action bar style generator, but that doesn't work. Here's what I tried adding:

<style name="ButtonLegacyButton" parent="android:Widget.Holo.Light.Button">
  <item name="android:background">@drawable/legacybutton_btn_default_holo_light</item>
</style>

<style name="ImageButtonLegacyButton" parent="android:Widget.Holo.Light.ImageButton">
  <item name="android:background">@drawable/legacybutton_btn_default_holo_light</item>
</style>

Those are new drawables that I generated with http://android-holo-colors.com/

No programmatic trickery I try in the onStart method seems to get anything to "stick" on the buttons either.

I found this blog here: http://android.codeandmagic.org/why-android-dialogfragment-confuses-me-part1/#comment-28043 which describes my problem exactly, except they go in a different direction and never answer the problem I have.

Any ideas of other things to try?

EDIT: I also have a styles.xml that's not being used. Here are the rest of the files requested.

Here is my Android Manifest:

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

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/legacy_icon"
        android:label="@string/app_name"
        android:theme="@style/Theme.Legacylogo">
        <activity
            android:name="com.example.legacy.GameListActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        ... other activities
    </application>

</manifest>

Here is my entire styles_legacylogo.xml:

<resources>

    <style name="Theme.Legacylogo" parent="@style/Theme.AppCompat.Light">
        <item name="android:actionBarItemBackground">@drawable/selectable_background_legacylogo</item>
        <item name="android:popupMenuStyle">@style/PopupMenu.Legacylogo</item>
        <item name="android:dropDownListViewStyle">@style/DropDownListView.Legacylogo</item>
        <item name="android:actionBarTabStyle">@style/ActionBarTabStyle.Legacylogo</item>
        <item name="android:actionDropDownStyle">@style/DropDownNav.Legacylogo</item>
        <item name="android:actionBarStyle">@style/ActionBar.Transparent.Legacylogo</item>
        <item name="android:actionModeBackground">@drawable/cab_background_top_legacylogo</item>
        <item name="android:actionModeSplitBackground">@drawable/cab_background_bottom_legacylogo</item>
        <item name="android:actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Legacylogo</item>
        <item name="android:spinnerItemStyle">@style/SpinnerItem</item>
        <item name="android:spinnerDropDownItemStyle">@style/SpinnerItem.DropDownItem</item>
    </style>

    <style name="ActionBar.Solid.Legacylogo" parent="@android:style/Widget.Holo.ActionBar.Solid">
        <item name="android:background">@drawable/ab_solid_legacylogo</item>
        <item name="android:backgroundStacked">@drawable/ab_stacked_solid_legacylogo</item>
        <item name="android:backgroundSplit">@drawable/ab_bottom_solid_legacylogo</item>
        <item name="android:progressBarStyle">@style/ProgressBar.Legacylogo</item>
    </style>

    <style name="ActionBar.Transparent.Legacylogo" parent="@android:style/Widget.Holo.ActionBar">
        <item name="android:background">@drawable/ab_transparent_legacylogo</item>
        <item name="android:progressBarStyle">@style/ProgressBar.Legacylogo</item>
    </style>

    <style name="PopupMenu.Legacylogo" parent="@android:style/Widget.Holo.ListPopupWindow">
        <item name="android:popupBackground">@drawable/menu_dropdown_panel_legacylogo</item>    
    </style>

    <style name="DropDownListView.Legacylogo" parent="@android:style/Widget.Holo.ListView.DropDown">
        <item name="android:listSelector">@drawable/selectable_background_legacylogo</item>
    </style>

    <style name="ActionBarTabStyle.Legacylogo" parent="@android:style/Widget.Holo.ActionBar.TabView">
        <item name="android:background">@drawable/tab_indicator_ab_legacylogo</item>
    </style>

    <style name="DropDownNav.Legacylogo" parent="@android:style/Widget.Holo.Spinner">
        <item name="android:background">@drawable/spinner_background_ab_legacylogo</item>
        <item name="android:popupBackground">@drawable/menu_dropdown_panel_legacylogo</item>
        <item name="android:dropDownSelector">@drawable/selectable_background_legacylogo</item>
    </style>

    <style name="ProgressBar.Legacylogo" parent="@android:style/Widget.Holo.ProgressBar.Horizontal">
        <item name="android:progressDrawable">@drawable/progress_horizontal_legacylogo</item>
    </style>

    <style name="ActionButton.CloseMode.Legacylogo" parent="@android:style/Widget.Holo.ActionButton.CloseMode">
        <item name="android:background">@drawable/btn_cab_done_legacylogo</item>
    </style>

    <style name="SpinnerItem" parent="@android:style/Widget.TextView.SpinnerItem">
        <item name="android:textColor">#fef7e7</item>
    </style>

    <style name="SpinnerItem.DropDownItem" parent="@android:style/Widget.DropDownItem.Spinner">
        <item name="android:textColor">#fef7e7</item>
    </style>

    <style name="ButtonLegacyButton" parent="android:Widget.Holo.Light.Button">
      <item name="android:background">@drawable/legacybutton_btn_default_holo_light</item>
    </style>

    <style name="ImageButtonLegacyButton" parent="android:Widget.Holo.Light.ImageButton">
      <item name="android:background">@drawable/legacybutton_btn_default_holo_light</item>
    </style>

    <!-- this style is only referenced in a Light.DarkActionBar based theme -->
    <style name="Theme.Legacylogo.Widget" parent="@android:style/Theme.Holo">
        <item name="android:popupMenuStyle">@style/PopupMenu.Legacylogo</item>
        <item name="android:dropDownListViewStyle">@style/DropDownListView.Legacylogo</item>
    </style>

</resources>
like image 240
JuniorIncanter Avatar asked Jul 11 '14 06:07

JuniorIncanter


1 Answers

Styling the default AlertDialog is extremely tricky and not really supported, that said it is possible, with some small caveats.

In your style.xml add a custom theme entry for the dialog:

<style name="CustomTheme.Dialog" parent="android:Theme.Holo.Light.Dialog">
    <item name="android:buttonBarButtonStyle">@style/CustomTheme.Dialog.Button</item>
    <!-- See caveat -->
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
    <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
</style>

Then add a style for the button itself:

<style name="CustomTheme.Dialog.Button" parent="@android:style/Widget.Holo.Light.Button.Borderless.Small">
    <item name="android:background">@drawable/legacybutton_btn_default_holo_light</item>
</style>

In your fragment extension where you create the builder pass it the reference to the custome theme:

builder = new AlertDialog.Builder(getActivity(), R.style.CustomTheme_Dialog);

Essentially that's it.

Caveats: The style and theme of AlertDialog are not public so they cannot be used as the parent entry of a new theme. In order to "correctly" extend it you have to duplicate the differences between the styles of Dialog and AlertDialog. This really isn't a huge issue but you should be aware that changes in the styling of the platform that specifically touch AlertDialog may not entirely transition to your app without intervention; Just something to keep in mind.

Unfortunately in order to really see how this works you really need to dig through the Android source and look at how all the files are applied. https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/AlertDialog.java https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/layout/alert_dialog_holo.xml https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/attrs.xml https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/styles.xml https://android.googlesource.com/platform/frameworks/base/+/master/core/res/res/values/themes.xml

Tracing generally would start with the layout then into attr, style or theme depending.

I will freely admit that once I figured out how to do this ... sometime last year, I stopped digging so I cannot fully explain why modifying the style of a DialogFragment after it is created is not allowed but the reference docs do make mention of it in passing in the setStyle method entry. Those styles seem to be oddly immutable after onCreate is called.

Please let me know if you would like anything expanded on.

like image 110
Matt T. Avatar answered Oct 05 '22 23:10

Matt T.