Android: DialogPreference color/style? - android

My main preference activity is set to "#android:style/Theme.Light". One of my preferences is a DialogPreference who's Dialog contains a ListView. The ListView's dialog is dark grey (because DialogPreference uses AlertBuilder which creates dark grey dialogs) and the text in the list is black (because Theme.Light causes listViews to have black text). Is there an easy way to either get the ListView to behave with the same style as the dark dialog? Or to get the dark dialog to behave with the same style as the light activity?
EDIT:
Based on Merlin's comments, it seems like what I should try to do is create a LightDialog Theme. In order to do this I tried: 1. extending android's Theme.Light and adding the dialogy properties from Theme.Dialog
<style name="Theme.LightDialog" parent="#android:style/Theme.Light">
<item name="android:windowFrame">#null</item>
<item name="android:windowTitleStyle">#android:style/DialogWindowTitle</item>
<item name="android:windowBackground">#android:drawable/panel_background</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowAnimationStyle">#android:style/Animation.Dialog</item>
</style>
... and 2. extending android's Theme.Dialog and adding the lighty properties from Theme.Light.
<style name="Theme.LightDialog" parent="#android:style/Theme.Dialog">
<item name="android:windowBackground">#drawable/screen_background_light</item>
<item name="android:colorBackground">#android:color/background_light</item>
<item name="android:colorForeground">#androidcolor/bright_foreground_light</item>
<item name="android:colorForegroundInverse">#android:color/bright_foreground_light_inverse</item>
<item name="android:textColorPrimary">#android:color/primary_text_light</item>
<item name="android:textColorSecondary">#android:color/secondary_text_light</item>
<item name="android:textColorTertiary">#android:color/tertiary_text_light</item>
<item name="android:textColorPrimaryInverse">#android:color/primary_text_dark</item>
<item name="android:textColorSecondaryInverse">#android:color/secondary_text_dark</item>
<item name="android:textColorTertiaryInverse">#android:color/tertiary_text_dark</item>
<item name="android:textColorPrimaryDisableOnly">#android:color/primary_text_light_disable_only</item>
<item name="android:textColorPrimaryInverseDisableOnly">#android:color/primary_text_dark_disable_only</item>
<item name="android:textColorPrimaryNoDisable">#android:color/primary_text_light_nodisable</item>
<item name="android:textColorSecondaryNoDisable">#android:color/secondary_text_light_nodisable</item>
<item name="android:textColorPrimaryInverseNoDisable">#android:color/primary_text_dark_nodisable</item>
<item name="android:textColorSecondaryInverseNoDisable">#android:color/secondary_text_dark_nodisable</item>
<item name="android:textColorHint">#android:color/hint_foreground_light</item>
<item name="android:textColorHintInverse">#android:color/hint_foreground_dark</item>
</style>
Both of these attempts failed because they use non-public attributes. Any suggestions on how to create a LightDialog theme?

You can inherit defult themes when creating styles in Android.
Please read the documentation on Applying Styles and Themes specifically the section on inheritance
You should be able to take Theme.light and correct any issues that you have with it.
You may find that different vendors alter the themes on their devices so if you are targeting a broad range of hardware then you may be better creating a full theme to ensure that your app is consistent on all platforms.
UPDATE
As stated in this answer Consistent UI color in all Android devices there are public and non-public attributes. The answer provides a link to a list of public attributes however kernel.org is still down so you will need to dig through the source for core/res/res/values/public.xml

You can specify style of DialogPreference's dialog using android:alertDialogTheme (supported starting from API 11) them property of preferences activity:
<style name="PreferencesActivityTheme" parent="#style/Theme.AppCompat.Light.DarkActionBar">
<item name="android:alertDialogTheme">#style/Theme.MyDialog</item>
</style>
<style name="Theme.MyDialog" parent="#style/Theme.AppCompat.Light.Dialog">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>

I have a solution how you can do it programmatically (I think its the easier way):
public class CustomDialogPreference extends DialogPreference {
...
#Override
protected void showDialog(Bundle state) {
super.showDialog(state);
//changing color of divider
int divierId = getDialog().getContext().getResources()
.getIdentifier("android:id/titleDivider", null, null);
View divider = getDialog().findViewById(divierId);
divider.setBackgroundColor(getContext().getResources().getColor(R.color.light_orange));
//changing color of title textview
int titleId = getDialog().getContext().getResources()
.getIdentifier("android:id/alertTitle", null, null);
TextView title = (TextView) getDialog().findViewById(titleId);
title.setTextColor(getContext().getResources().getColor(R.color.light_orange));
}
...
}

Related

Make an AndroidView's theme style come from Compose and change in light / dark mode

You style a CalendarView like so:
AndroidView({
CalendarView(android.view.ContextThemeWrapper(it, R.style.CustomCalendar)).apply {
dateTextAppearance = R.style.CustomDate
weekDayTextAppearance = R.style.CustomWeek
}
})
<style name="CustomDay" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/white</item>
</style>
<style name="CustomWeek" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/white</item>
</style>
<style name="CustomCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">#color/teal_700</item>
<item name="colorAccent">#color/purple_200</item>
<item name="colorOnPrimary">#color/purple_200</item>
<item name="colorSurface">#color/purple_200</item>
</style>
CalendarView does not let you programmatically set its colours anymore. They must come from a XML style.
Is it possible to make the colours for CalendarView come from the colours defined in Compose, rather than the colours defined in the XML?
Currently the duplication is vaguely manageable, except for the when the user changes to a dark mode Compose theme--then the CalendarView's colours won't change to dark mode; the dark mode only exists within Compose world.
Note: Android interaction in Compose is excellent. Yet Android views that demand xml styles force a duplication of Compose and XML styles and colours, if you decide you want Compose to be source of truth, and you also want to use Android Views. And how they switch during theme change is a question I still haven't answered sufficiently.
I'm guessing it's not possible to make Android XML style colours etc come from Compose.
But it is possible to make those XML styles changes when the Compose dark/light mode changes.
You check for a boolean that states if the user has chosen dark mode (I put it in my view model). And if so chose different XML style resources for that.
#Compose
fun AndroidCalendarView(
yourViewModel: YourViewModel = LocalViewModel.current
) {
var calTheme = R.style.CustomCalendar
var dateTheme = R.style.CustomDate
var weekTheme = R.style.CustomWeek
if (yourViewModel.darkTheme) {
calTheme = R.style.CustomCalendarDark
dateTheme = R.style.CustomDateDark
weekTheme = R.style.CustomDateWeek
}
AndroidView({
CalendarView(android.view.ContextThemeWrapper(it, calTheme)).apply {
dateTextAppearance = dateTheme
weekDayTextAppearance = weekTheme
}
})
}
This means your one theme xml style will have two sets of styles, one for light more and one for dark mode.
<style name="CustomDay" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/black</item>
</style>
<style name="CustomWeek" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/black</item>
</style>
<style name="CustomCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">#color/teal_700</item>
<item name="colorAccent">#color/purple_200</item>
<item name="colorOnPrimary">#color/purple_200</item>
<item name="colorSurface">#color/purple_200</item>
</style>
<style name="CustomDayDark" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/white</item>
</style>
<style name="CustomWeekDark" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/white</item>
</style>
<style name="CustomCalendarDark" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">#color/teal_700</item>
<item name="colorAccent">#color/purple_200</item>
<item name="colorOnPrimary">#color/purple_200</item>
<item name="colorSurface">#color/purple_200</item>
</style>
Hacky, but it works.
Is it possible to make the colours for CalendarView come from the colours defined in Compose, rather than the colours defined in the XML?
Short answer: no.
From the doc:
Note: Ideally, there would be a way to define your theme and styling in Compose, and have it automatically reflected in the View system, but that's not possible due to the limitations of the view styling system.
The style and the colors used by the CalendarView are defined in the code and it uses resources defined in the xml files. This means your app's theming will have 2 sources of truth: the View-based theme and the Compose theme.
To handle the dark mode just define the your themeoverlay and styles in the res/values-night folder:
For example:
<style name="CustomDate" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/red600</item>
</style>
<style name="CustomWeek" parent="android:TextAppearance.DeviceDefault.Small">
<item name="android:textColor">#color/red600Light</item>
</style>
<style name="CustomCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
<item name="android:textColorPrimary">#color/purple_700</item>
<item name="colorAccent">#color/teal_200</item>
<item name="colorOnPrimary">#color/teal_200</item>
<item name="colorSurface">#color/teal_200</item>
</style>
Light mode:
Dark mode:.

Custom BiometricPrompt.Builder

Can we modify/custom ourBiometricPrompt?
For example right now i use smth like this:
BiometricPrompt.Builder(AppResources.appContext)
.setTitle("title")
.setSubtitle("subTitle")
.setDescription("description")
.setNegativeButton("Cancel", AppResources.appContext?.mainExecutor,
DialogInterface.OnClickListener { dialogInterface, i -> biometricCallback.onAuthenticationCancelled() })
.build()
.authenticate(CancellationSignal(), AppResources.appContext?.mainExecutor,
BiometricCallbackV28(biometricCallback))
Do I have the ability to change the style of the text, title, negativeButton color?
Update2: beta01
The change with the alpha version was that the fingerprint dialog uses android.app.AlertDialog and the new beta01 uses androidx.appcompat.app.AlertDialog which has a private style.
Then to override that style we have to override androidx.appcompat.R.attr.alertDialogTheme reference in our styles.xml, we can do it replacing <item name="android:alertDialogTheme">#style/CustomAlertTheme</item> by <item name="alertDialogTheme">#style/CustomAlertTheme</item> in my case thay I only wanted to change the button text color, I just added <item name="buttonBarNegativeButtonStyle">#style/NegativeButtonStyle</item> and the same for posivtive, because replacing alertDialogTheme changes other things that I did not want to.
My styles.xml now:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="android:textColor">#color/black</item>
<item name="android:buttonStyle">#style/WibleButtonStyle</item>
<item name="buttonBarNegativeButtonStyle">#style/NegativeButtonStyle</item>
</style>
<style name="NegativeButtonStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/dark_blue</item>
</style>
Update: beta01
This trick is not working anymore. I'll try if I can find another way to do it.
I found two ways to do it, none of these are specific for the BiometricPrompt, one is to override the theme button style:
<item name="android:buttonStyle">#style/CustomButtonStyle</item>
another option is to override your alert dialog theme:
AppTheme style
<item name="android:alertDialogTheme">#style/AlertDialogTheme</item>
<style name="AlertDialogTheme" parent="ThemeOverlay.AppCompat.Dialog.Alert">
<item name="android:buttonBarNegativeButtonStyle">#style/NegativeButtonStyle</item>
<item name="android:buttonBarPositiveButtonStyle">#style/PositiveButtonStyle</item>
</style>
<style name="NegativeButtonStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textSize">10sp</item>
<item name="android:textColor">#color/primary_text</item>
</style>
<style name="PositiveButtonStyle" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textColor">#color/primary_text</item>
</style>
And then you can apply a specific theme to a specific activity. Maybe they could open the API to allow styles, but I had to change the color because it was impossible to see the buttons (everything was white) and this is what I found to solve my problem. I hope it helps you.
You can't set properties on the prompt that aren't exposed through its Builder - the UI is provided by the system, and is designed to be uniform throughout all apps.
This is sort of the main point of this API, this way the user becomes familiar with the prompt and knows that whatever they're interacting with is safe to use.
Can we modify/custom our BiometricPrompt?
The BiometricPrompt uses the "buttonStyle" style that is set for your theme, which you can adjust in the styles.xml
Keep in mind that this is the default button style, so if you do not want other buttons to change you would have to assign buttons etc. their own style. (and dialogs etc.)
For example, if you only want the text color to be different for the BiometricPrompt, you could do something like this:
<style name="myTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="buttonStyle">#style/ButtonPrimaryStyle</item>
</style>
<style name="ButtonPrimaryStyle" parent="ButtonParentStyle">
<item name="android:textColor">454545</item>
</style>
<style name="ButtonPrimaryStyleMain" parent="ButtonPrimaryStyle">
<item name="android:textColor">e2e2e2</item>
</style>
This would make the BiometricPrompt have a dark grey text for the cancel button, while every button with the "ButtonPrimaryStyleMain" style will have a lightgrey, almost white, text color.
You would also have to assign this theme to your application in the manifest.
<application
android:theme="#style/myTheme"

Styling my app with custom colors

I'm trying to apply some styles to my app. I've created a custom theme for the ActionBar using this actionbarstylegenerator.
But I want to change also in my app, the stock blue Holo color, to a red one, at least on buttons.
So, I have the custom theme for the ActionBar (Compat), and for the other side, a custom theme to change the Holo color.
In my app, I have defined the custom theme for the Actionbar, and I want to set the custom Holo theme inside the Actionbar's theme, but I don't know how to call, or where can I find the item name's whose define the variable you want to modify.
This is, I need to set this:
<style name="ColorTheme" parent="android:Theme.Black">
<item name="android:checkboxStyle">#style/CheckBoxColorTheme</item>
<item name="android:buttonStyle">#style/ButtonColorTheme</item>
<item name="android:imageButtonStyle">#style/ImageButtonColorTheme</item>
</style>
Inside of this:
<style name="Theme.CustomActionBarTheme" parent="#style/Theme.AppCompat">
<item name="actionBarItemBackground">#drawable/ab_selectable_background</item>
<item name="popupMenuStyle">#style/PopupMenu</item>
<item name="dropDownListViewStyle">#style/DropDownListView</item>
<item name="actionBarTabStyle">#style/ActionBarTabStyle</item>
<item name="actionDropDownStyle">#style/DropDownNav</item>
<item name="actionBarStyle">#style/ActionBar.Transparent</item>
<item name="actionModeBackground">#drawable/cab_background_top_customactionbartheme</item>
<item name="actionModeSplitBackground">#drawable/cab_background_bottom_customactionbartheme</item>
<item name="actionModeCloseButtonStyle">#style/ActionButton.CloseMode</item>
</style>
Maybe you need to do this?
<style name="ColorTheme" parent="Theme.CustomActionBarTheme">
<item name="android:checkboxStyle">#style/CheckBoxColorTheme</item>
<item name="android:buttonStyle">#style/ButtonColorTheme</item>
<item name="android:imageButtonStyle">#style/ImageButtonColorTheme</item>

Custom style is interfering with platform dialogs

I've created a custom theme for my app, and it looks great! However, I've noticed that some default platform dialogs, such as the context menu when long-pressing an EditText doesn't show correctly.
On the left, a context menu through my app. On the right, a standard context menu through a platform app.
Here's my style.xml:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.Styled" parent="Theme.Sherlock">
<!-- ... various app styles ... -->
<item name="android:alertDialogStyle">#style/DialogHolo</item>
<item name="android:dialogTheme">#style/DialogHolo</item>
</style>
<style name="DialogHolo" parent="android:style/Theme.Dialog">
<item name="android:fullDark">#drawable/bg_dialog_full</item>
<item name="android:topDark">#drawable/bg_dialog_top</item>
<item name="android:centerDark">#drawable/bg_dialog_middle</item>
<item name="android:bottomDark">#drawable/bg_dialog_bottom</item>
<item name="android:fullBright">#drawable/bg_dialog_full</item>
<item name="android:centerBright">#drawable/bg_dialog_middle</item>
<item name="android:bottomBright">#drawable/bg_dialog_bottom</item>
<item name="android:bottomMedium">#drawable/bg_dialog_bottom</item>
<item name="android:centerMedium">#drawable/bg_dialog_middle</item>
<item name="android:textColor">#ffe6e7e8</item>
</style>
</resources>
Is it possible to either have these dialogs use the default style or get the text to appear in the desired text color?
I never found an elegant solution for this, and instead simply provided a theme defined separately in my style.xml when displaying a custom dialog.

Styling ActionBar dropdown menu

I'm using a custom theme that inherits from DarkActionBar and I want to customize dropdown menu to be white like when using Light Holo theme.
I've been able to change the background to white using:
<style name="MyTheme" parent="#style/Theme.Light.DarkActionBar">
<item name="android:actionDropDownStyle">#style/MyDropDownNav</item>
</style>
<style name="MyDropDownNav">
<item name="android:background">#drawable/spinner_background_white</item>
<item name="android:popupBackground">#drawable/menu_dropdown_panel_whyite</item>
<item name="android:dropDownSelector">#drawable/selectable_background_white</item>
</style>
But I haven't any clue of how to change the text color to black. Because after setting white drawable the problem is that text isn't visible because is white on white background.
I answer myself after some investigation.
In addition to question's styling you need to:
Customize android:spinnerDropDownItemStyle for actionBarWidgetTheme changing it's text appearance.
Also don't forget that dropdown list is managed by the adapter you use. Then if you used the standard one (simple_dropdown_item_1line) there's no problem. But if you used a custom one like me (to be able to add an icon) don't forget to apply style="?attr/spinnerDropDownItemStyle" in your layout TextView.
Then final custom style is:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.myapp" parent="#style/Theme.Light.DarkActionBar">
<item name="android:actionDropDownStyle">#style/myapp_DropDownNav</item>
<item name="android:actionBarWidgetTheme">#style/myapp.actionBarWidgetTheme</item>
</style>
<style name="myapp.actionBarWidgetTheme" parent="#style/Theme.">
<item name="android:spinnerDropDownItemStyle">#style/myapp.Widget.DropDownItem.Spinner</item>
</style>
<style name="myapp_DropDownNav" parent="#style/Widget.Spinner.DropDown.ActionBar">
<item name="background">#drawable/spinner_background_ab_myapp</item>
<item name="android:background">#drawable/spinner_background_ab_myapp</item>
<item name="android:popupBackground">#drawable/menu_dropdown_panel_myapp</item>
<item name="android:dropDownSelector">#drawable/selectable_background_myapp</item>
</style>
<style name="myapp.Widget.DropDownItem.Spinner" parent="Widget.DropDownItem.Spinner">
<item name="android:textAppearance">#style/myapp.TextAppearance.Widget.DropDownItem</item>
</style>
<style name="myapp.TextAppearance.Widget.DropDownItem" parent="TextAppearance.Widget.DropDownItem">
<item name="android:textColor">#color/black</item>
</style>
Where drawables in myapp_DropDownNav are white background ones that you can generate with ActionBar Style generator in Android Asset Studio
Try setting itemTextAppearance. That should achieve what you want.
I have stumbled on what may be the simplest way to do this. I was working with the AppCompat library.
<style name="ApplicationTheme" parent="#style/Theme.AppCompat">
<item name="android:actionBarWidgetTheme">#style/Theme.AppCompat.Light</item>
<item name="actionBarWidgetTheme">#style/Theme.AppCompat.Light</item>
</style>
My advice is to simply inherit from the Sherlock.Light theme and change the applicable fields to the Dark values. For my app, we wanted a white "up" icon, and white text for the action labels. I don't provide dark versions of my actionbar icons, so they are all white anyway. So after several hours messing around with it and following different people's suggestions, I finally found what I was looking for in the ABS themes file.
I inherit from Sherlock.Light (well, technically HoloEverywhereLight.Sherlock but...) and change:
<item name="android:actionMenuTextColor">#color/White</item>
<item name="actionMenuTextColor">#color/White</item>
<item name="android:homeAsUpIndicator">#drawable/abs__ic_ab_back_holo_dark</item>
<item name="homeAsUpIndicator">#drawable/abs__ic_ab_back_holo_dark</item>
<item name="android:dividerVertical">#drawable/abs__list_divider_holo_dark</item>
<item name="dividerVertical">#drawable/abs__list_divider_holo_dark</item>
That's it. It's way simpler and easier than trying to extend classes, restyle things in code, etc.

Categories

Resources