How to style buttons in Alert Dialog Fragment using Material Design? - android

I'd like to change the default button styling on an alert dialog.
The standard Alert Dialog Fragment (in Android L) looks like this:
I'd like the right button to be styled as a normal button instead of a borderless button. Google itself seems to use this pattern in various dialogs, such as:
Does anyone know if this is possible, without recreating the whole dialog from scratch?

You can style the button in the theme with attributes: android:buttonBarPositiveButtonStyle, android:buttonBarNegativeButtonStyle, and android:buttonBarNeutralButtonStyle.

Ok, the issue is solved automagically by updating to the (just released) release 21. Now the buttons are automatically in primary color :-)
EDIT: They are not in primary color, but in Android's basic turquoise..

This solution is for changing button color with material effect in AppCompatDialogFragment.
<android.support.v7.widget.AppCompatButton
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="#string/buttin"
android:theme="#style/AppTheme.MyButton"
/>
Style file - v21
<style name="AppTheme.MyButton" parent="Theme.AppCompat.Dialog.Alert">
<item name="android:colorButtonNormal">#color/button_color</item>
<item name="android:textColor">#color/text_color</item>
</style>
Style file
<style name="AppTheme.MyButton" parent="Theme.AppCompat.Dialog.Alert">
<item name="colorButtonNormal">#color/button_color</item>
<item name="android:textColor">#color/text_color</item>
</style>

Kotlin
In your app's theme/style, add the following lines:
<item name="android:buttonBarNegativeButtonStyle">#style/NegativeButtonStyle</item>
<item name="android:buttonBarPositiveButtonStyle">#style/PositiveButtonStyle</item>
<item name="android:buttonBarNeutralButtonStyle">#style/NeutralButtonStyle</item>
Then add the following styles:
<style name="NegativeButtonStyle" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">#color/red</item>
</style>
<style name="PositiveButtonStyle" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">#color/red</item>
</style>
<style name="NeutralButtonStyle"
parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">#00f</item>
</style>
Using this method makes it unneccessary to set the theme in the AlertDialog builder.

Related

MaterialComponents theme alert dialog buttons

Recently I switched from support library to com.google.android.material:material:1.0.0
But now I have a problem, in this pages there's a note https://github.com/material-components/material-components-android/blob/master/docs/getting-started.md
Note: Using a Material Components theme enables a custom view inflater which replaces default components with their Material counterparts. Currently, this only replaces Button XML components with MaterialButton.
And the theme I am using
Theme.MaterialComponents.Light.NoActionBar
does exactly what it says in that note, it replaces AlertDialog Buttons to MaterialButtons but the problem is that by default MaterialButtons are colored background and now the buttons looks like this:
How can I make them borderless and backgroundless again?
PS I am using alert builder to create alert dialogs:
android.app.AlertDialog.Builder
I figured out what was causing this problem. I need to use different AlertDialog class:
androidx.appcompat.app.AlertDialog
When I switched to this everything started working as expected. Here's where I found the solution:
https://github.com/material-components/material-components-android/issues/162
When using com.google.android.material:material:1.0.0 and androidx.appcompat.app.AlertDialog you can customize each button in the buttonBar by using Widget.MaterialComponents.Button.TextButton as parent.
val builder: AlertDialog.Builder = AlertDialog.Builder(ContextThemeWrapper(context, R.style.AlertDialogTheme))
Use the default layout or add a custom by builder.setView(R.layout.my_dialog)
In your styles:
<style name="AlertDialogTheme" parent="Theme.MaterialComponents.Light.Dialog.Alert">
<item name="buttonBarPositiveButtonStyle">#style/Alert.Button.Positive</item>
<item name="buttonBarNegativeButtonStyle">#style/Alert.Button.Neutral</item>
<item name="buttonBarNeutralButtonStyle">#style/Alert.Button.Neutral</item>
</style>
<style name="Alert.Button.Positive" parent="Widget.MaterialComponents.Button.TextButton">
<item name="backgroundTint">#color/transparent</item>
<item name="rippleColor">#color/colorAccent</item>
<item name="android:textColor">#color/colorPrimary</item>
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">false</item>
</style>
<style name="Alert.Button.Neutral" parent="Widget.MaterialComponents.Button.TextButton">
<item name="backgroundTint">#color/transparent</item>
<item name="rippleColor">#color/colorAccent</item>
<item name="android:textColor">#color/gray_dark</item>
<item name="android:textSize">14sp</item>
</style>
If you are using the Material Components library the best way to have an AlertDialog is to use the MaterialAlertDialogBuilder.
new MaterialAlertDialogBuilder(context)
.setTitle("Dialog")
.setMessage("Lorem ipsum dolor ....")
.setPositiveButton("Ok", /* listener = */ null)
.setNegativeButton("Cancel", /* listener = */ null)
.show();
It is the default result:
If you want also to apply a different style or color to the buttons you can check this answer.
I tested the above answers. Although I got a good idea, none worked for my case. So, this is my answer.
Make sure to have android:theme="#style/AppMaterialTheme" in your manifest file under Application or Activity.
Open your Styles.xml file and change it based on the following.
<style name="AppMaterialTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">#color/primaryBlue</item>
<item name="colorPrimaryDark">#color/primaryBlue</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="colorControlActivated">#color/primaryBlue</item>
<item name="colorControlHighlight">#color/colorAccent_main</item>
<item name="colorButtonNormal">#color/white</item>
<item name="materialAlertDialogTheme">#style/AlertDialogMaterialTheme</item>
</style>
<style name="AlertDialogMaterialTheme" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="buttonBarPositiveButtonStyle">#style/Alert.Button.Positive</item>
<item name="buttonBarNegativeButtonStyle">#style/Alert.Button.Negative</item>
</style>
<style name="Alert.Button.Positive" parent="Widget.MaterialComponents.Button.UnelevatedButton">
<item name="android:fillColor">#color/color_0054BB</item>
<item name="android:textColor">#color/white</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="rippleColor">#color/colorAccent_main</item>
</style>
<style name="Alert.Button.Negative" parent="Widget.MaterialComponents.Button.OutlinedButton">
<item name="strokeColor">#color/color_0054BB</item>
<item name="android:textColor">#color/color_0054BB</item>
<item name="android:textAllCaps">false</item>
<item name="android:textSize">14sp</item>
<item name="android:layout_marginEnd">8dp</item>
<item name="rippleColor">#color/colorAccent_main</item>
</style>
You won't need to apply the theme to your AlertDialog as your Activity applies the theme to it. So, create the dialog normally.
The result will be.
First, it's better to use use MaterialAlertDialog if you are using Material Theme.
You can read more here – Material.io → Theming dialogs
MaterialAlertDialogBuilder(context)
.setTitle(R.string.confirm)
.setMessage(R.string.logout)
.setPositiveButton(R.string.logout_alert_positive) { _, _ -> activity?.logout() }
.setNegativeButton(R.string.never_mind, null)
.show()
This is the layout.xml of the MaterialAlertDialog actions. As you can see there are 3 buttons and each has their own styles. So, here is how you can change them.
Step 1: Tell Android that you want to alter the default MaterialAlertDialog theme.
<style name="Base.AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
...
<item name="materialAlertDialogTheme">#style/AlertDialog</item>
...
</style>
Step 2: Tell Android that you want to alter a specific button style. buttonBarNeutralButtonStyle, buttonBarNegativeButtonStyle or buttonBarPositiveButtonStyle
<style name="AlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="buttonBarNegativeButtonStyle">#style/NegativeButtonStyle</item>
</style>
Step 3: Define your custom style
<style name="NegativeButtonStyle" parent="Widget.MaterialComponents.Button.TextButton">
<item name="android:textColor">#FF0000</item>
</style>
Found another solution for this with using MaterialComponents here: https://issuetracker.google.com/issues/116861837#comment9
<style name="Theme.Custom.Material.Alert.Dialog.Light" parent="Theme.MaterialComponents.Light.Dialog.Alert">
<item name="materialButtonStyle">#style/Widget.AppCompat.Button.Borderless</item>
</style>
<style name="Theme.Custom.Material.Base.Light" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:dialogTheme">#style/Theme.Custom.Material.Alert.Dialog.Light</item>
<item name="android:alertDialogTheme">#style/Theme.Custom.Material.Alert.Dialog.Light</item>
....
</style>
Though it is still not "intended behavior" to me.
If you don't want to use androidx.appcompat.app.AlertDialog, you can just redefine the style of the dialog buttons:
In your style.xml :
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
...
<item name="android:buttonBarButtonStyle">#style/DialogButton</item>
...
</style>
<style name="DialogButton" parent="Widget.MaterialComponents.Button.TextButton"/>
If you are using the com.android.support:design:28.0.0 library, using android.support.v7.app.AlertDialog works as expected.

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"

Date Picker Dialog with AppCompat theme

In the image above (don't worry about the calendar positioning), the whole calendar is the correct theme color except the green of the chosen date. I've tried many things but not been able to change this last part of the theme! I'm using Theme.AppCompat.Light.DarkActionBar and have gotten to the current point by changing the DatePickerDialogTheme's colorAccent. I've also tried changing
dayOfWeekBackground
dayOfWeekTextAppearance
headerMonthTextAppearance
headerDayOfMonthTextAppearance
headerYearTextAppearance
headerSelectedTextColor
yearListItemTextAppearance
yearListSelectorColor
calendarTextColor
calendarSelectedTextColor
And those don't seem to have done it. Here's my XML, thank you in advance!
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorRed</item>
<item name="colorPrimaryDark">#color/colorRed</item>
<item name="colorAccent">#color/colorRed</item>
<item name="android:datePickerDialogTheme">#style/MyDatePickerDialogTheme</item>
</style>
<style name="MyDatePickerDialogTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:colorAccent">#color/colorRed</item>
</style>
To change the colour of the circle of the selected date, use
<item name="android:colorControlActivated">#color/your_colour</item>
use this theme
<style name="MyDatePickerDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="android:colorAccent">#color/colorRed</item>
<item name="android:datePickerStyle">#style/MyDatePickerStyle</item>
<item name="android:colorAccent">#color/primaryDark</item>
</style>
and
<style name="MyDatePickerStyle" parent="#android:style/Widget.Material.Light.DatePicker">
<item name="android:headerBackground">#color/primary</item>
<item name="android:calendarTextColor">#color/primaryDark</item>
<item name="android:dayOfWeekBackground">#color/primaryDark</item>
<item name="android:yearListSelectorColor">#color/accent</item>
<item name="android:datePickerMode">calendar</item>
</style>
For the selected day's colour you do have to use colorAccent, here's what works me:
<style name="PopupDialogTheme" parent="Theme.AppCompat.Light.Dialog.Alert">
<!--selected day's color: define your own-->
<item name="colorAccent">#color/yourColour</item>
</style>
and in your class instantiate like this:
final AlertDialog.Builder datePickerBuilder = new AlertDialog.Builder(ProviderMainActivity.this, R.style.PopupDialogTheme);
// ... do something with your dialog, i.e. .show()
Regarding the other attributes that were mentioned in the question: look up their reference and find out what params they take (in the xml).
For example for setting the year/month/day's colour in the header, you have to define a text appearance (CodeFont) like this:
<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/dpPickDate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:headerBackground="#drawable/calendar_header"
android:headerYearTextAppearance="#style/YourCodeFont"
android:headerMonthTextAppearance="#style/YourCodeFont"
android:headerDayOfMonthTextAppearance="#style/YourCodeFont"/>
note YourCodeFont, which you need to define in your styles.xml:
<style name="PopupCodeFont" parent="#android:style/TextAppearance.Medium">
<item name="android:textColor">#color/black</item>
</style>
You can't, for example do this:
android:headerYearTextAppearance="#color/black"
Also note that some of these attributes, in example headerYearTextAppearance require API 21+, so better handle and test for previous versions.

Android - change dialog title style of all dialogs in application

Is there a way I can change all the alert dialogs appearing in my Android application? I want to change the dialogs that are system generated as well (like the Edit Text dialog that opens up when you long tap on any EditText). I want to change the title font color and size of all the dialogs in my app.
Is there a way to do it?
I have tried setting android:alertDialogTheme in my theme. But it seems to be not working. Code following -
<style name="Theme.DLight" parent="android:Theme.Light.NoTitleBar">
<item name="android:alertDialogTheme">#style/DialogStyle</item>
</style>
and
<style name="DialogStyle" parent="android:Theme" >
<item name="android:windowBackground">#drawable/background_holo_light</item>
<item name="android:textColor">#014076</item>
</style>
EDIT
I'm not invoking a dialog from my code. It's just the default dialog
that appears when you long click on any EditText. Generally it
contains the keyboard options like Select word, Select all, Input
method etc.
In you dialog theme, the attribute you need to modify windowTitleStyle. There, reference a style for your title and define a text appearance for this title. For example, to display your title red and bold:
<style name="AppTheme" parent="#android:style/Theme.Holo">
...
<item name="alertDialogTheme">#style/AppTheme.AlertDialog</item>
</style>
<style name="DialogStyle" parent="#style/Theme.Holo.Dialog.Alert">
...
<item name="android:windowTitleStyle">#style/DialogWindowTitle_Custom</item>
</style>
<style name="DialogWindowTitle_Custom" parent="#style/DialogWindowTitle_Holo">
<item name="android:maxLines">1</item>
<item name="android:scrollHorizontally">true</item>
<item name="android:textAppearance">#style/TextAppearance_DialogWindowTitle</item>
</style>
<style name="TextAppearance_DialogWindowTitle" parent="#android:style/TextAppearance.Holo.DialogWindowTitle">
<item name="android:textColor">#android:color/holo_red_light</item>
<item name="android:textStyle">bold</item>
</style>
If you want to style a little bit more your AlertDialog, I wrote a blog post detailing the steps.
In styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
//All your other styles and add the one mntioned below.
<item name="alertDialogTheme">#style/AlertDialogStyle</item>
</style>
In the styles of AlertDialog add:
<style name="AlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">#color/colorAccent</item>
<item name="android:textColorPrimary">#color/primary_text</item>
<item name="android:editTextColor">#color/primary_text</item>
<item name="android:background">#color/white</item>
<item name="android:windowTitleStyle">#style/TextAppearance.AppCompat.Title</item>
</style>
windowTitleStyle is important to add as it will give your title that effect that you need.
Now simply use this Theme in your AlertDialog in any activity that you want like below:
AlertDialog.Builder dialog = new AlertDialog.Builder(this, R.style.AlertDialogStyle);

Want to overload Button style

I want to overload how an android Button looks, except I want to overload only one attribute i.e. the android:background. I know I could write something like:
<style name="App_TextButtonStyle" parent="???">
<item name="android:background">#drawable/filled_roundededges_nostroke</item>
</style>
Where parent="???" specifies which style I inherit from. My question is which style should I inherit from do that I get everything from the android default style for buttons and just define a new background.
I have used style for buttons without specifying "parent" attribute
<style name="BigButtonStyle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:background">#drawable/backbutton</item>
<item name="android:textColor">#FFFFFF</item>
<item name="android:textSize">8pt</item>
<item name="android:textStyle">bold</item>
<item name="android:layout_margin">10pt</item>
</style>
I think it could be enough for you to define your style without "parent".
This is mostly for future visitors, I found a solution to the problem:
<style name="App_TextButtonStyle" parent="#android:style/Widget.Button">
<item name="android:background">#drawable/filled_roundededges_nostroke</item>
</style>
#android:style/Widget.Button references the default style of the button in the currently selected theme. You could also use the holo widget button style #android:style/Widget.Holo.Button (available since api 11).
You might want to look in <android-sdk-install-folder>/platforms/android-XX/data/res/values for the files styles.xml and themes.xml to check out all styles android uses for a given platform version.

Categories

Resources