Overriding editTextStyle doesn't work with latest Material Components base style - android

In an app of mine, I'm using the Theme.MaterialComponents.Light.NoActionBar as a base style. In this style, which I call AppTheme, I'm trying to override editTextStyle to provide a custom style for com.google.android.material.textfield.TextInputEditText (according to the source code, it uses R.attr.editTextStyle as a default style).
This is my current theme, related to the TIEditText and TILayout:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
[ primary and secondary colors, OnColors, etc.]
<item name="editTextStyle">#style/AppTheme.TextInputEditText</item>
<item name="textInputStyle">#style/AppTheme.TextInputLayout</item>
[ Custom attribute for testing, defined in attrs.xml ]
<item name="textInputEditTextStyle">#style/AppTheme.TextInputEditText</item>
</style>
For some reason, even though I set editTextStyle, if I use it in code, it does not get applied:
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/tilFirstName"
style="?attr/textInputStyle"
android:hint="#string/label_firstname"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/firstName"
style="?attr/editTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="#={viewModel.firstName}" />
</com.google.android.material.textfield.TextInputLayout>
However if I replace the style of firstName with ?attr/textInputEditTextStyle, it works.
Why can't I override editTextStyle in the default theme? What the hell is going on?
Target SDK is 28, minSDK is 21, Material library version is 1.1.0-alpha06

Let's just move past the part where we all recognize that Android themes and styles are singularly the most absurd wasteland of hackery and guesswork ever devised by human beings.
This is an expansion on the previous answer. Same silly 'hack'. I was able to style the TextInputEditText by setting editTextStyle, but not where it intuitively belongs, but rather inside a custom materialThemeOverlay nested within the style defined for textInputStyle. Witness:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- works fine -->
<item name="textInputStyle">#style/AppTheme.TextInputLayoutStyle</item>
<!-- should work fine, doesn't work, happily ignored -->
<!-- <item name="editTextStyle">#style/AppTheme.TextInputEditTextStyle</item> -->
</style>
<style name="AppTheme.TextInputLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox">
<!-- other props (boxBackgroundMode, boxBackgroundColor, boxStrokeColor, etc) -->
<!-- can we set editTextStyle from here? Of course not! We should magically know we need a material theme overlay-->
<item name="materialThemeOverlay">#style/AppTheme.MaterialThemeOverlay</item>
</style>
<!-- style inception! a style, child of another style, whose only purpose is to refer to yet another style -->
<style name="AppTheme.MaterialThemeOverlay">
<item name="editTextStyle">#style/AppTheme.TextInputEditTextStyle</item>
</style>
<!-- finally, the style we SHOULD have been able to set from the theme -->
<style name="AppTheme.TextInputEditTextStyle" parent="#style/Widget.MaterialComponents.TextInputEditText.OutlinedBox">
<item name="android:textColor">#color/white</item>
</style>
All of the above ridiculousness and ANOTHER day of my life thrown in the trash, just to change the color of text. Thaaaaanks Aaaaaandroid.

For some reason, even though I set editTextStyle, if I use it in code, it does not get applied
It happens because the default styles of the TextInputLayout override the editTextStyle using the materialThemeOverlay attribute.
For example the Widget.MaterialComponents.TextInputLayout.FilledBox has this default style:
<style name="Widget.MaterialComponents.TextInputLayout.FilledBox" parent="Base.Widget.MaterialComponents.TextInputLayout">
<item name="materialThemeOverlay">
#style/ThemeOverlay.MaterialComponents.TextInputEditText.FilledBox
</item>
....
</style>
<style name="ThemeOverlay.MaterialComponents.TextInputEditText.FilledBox">
<item name="editTextStyle">#style/Widget.MaterialComponents.TextInputEditText.FilledBox</item>
</style>

Related

Android Material Chip Theme overriding

I want to customize a Material chip.
I would think this is how to do it:
<style name="AppTheme" parent="Theme.MaterialComponents.NoActionBar">
.... lots more theme stuff here
<item name="chipStyle">#style/MaterialChips</item>
<item name="chipGroupStyle">#style/MaterialChips</item>
<item name="chipStandaloneStyle">#style/MaterialChips</item>
</style>
<style name="MaterialChips" parent="Widget.MaterialComponents.Chip.Choice">
<item name="chipBackgroundColor">#color/chips</item>
</style>
None of the tags like chipStyle affect the chips. But if I set app:chipBackgroundColor="#color/chips" in xml it works.
It also works fine like this for other things like say <item name="materialAlertDialogTheme">#style/AlertDialogTheme</item>.
The material documentation (if you can call it that) is really not helping.
Your app theme is correct.
The default style used by Chip component is defined in the app theme by the chipStyle attribute.
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
<!-- Default style for chip component -->
<item name="chipStyle">#style/Widget.MaterialComponents.Chip.Action</item>
</style>
You can customize this style using for example:
<style name="AppTheme" parent="Theme.MaterialComponents.*">
<!-- Default value for chipStyle -->
<item name="chipStyle">#style/MaterialChips</item>
</style>
<style name="MaterialChips" parent="#style/Widget.MaterialComponents.Chip.Choice">
<!-- ... -->
<item name="chipBackgroundColor">#color/chips</item>
</style>
If you specify the style attribute in your layout, this style overrides the default value.
<com.google.android.material.chip.Chip
style="#style/Widget.MaterialComponents.Chip.Entry"
.../>
In this case the Chip uses the Widget.MaterialComponents.Chip.Entry style.
if you define chip style in layout xml, chip override your theme.
It may work if you clear chip style in layout xml.

Create style that extends from default style set in application theme

I have set the default button style in my application theme, so that it is applied to every button in the app.
There are few buttons that need to have their text capitalized in addition to default style. So what I'm trying to do is something like this
(the following code snippet doesn't work as I cannot set parent="?attr/materialButtonStyle"):
<style name="capitalizedButton" parent="?attr/materialButtonStyle">
<item name="android:textAllCaps">true</item>
</style>
Is it possible to extend a style defined in theme.xml? I don't want to refer to the local style that I'm setting in theme as that can change later, instead I intend to access it using theme attribute.
If the capitalization happens in addition to your custom default button style, there is no need to make the capitalization style a child of ?attr/materialButtonStyle (This cannot be done anyhow, as ?attr references an attribute in the currently applied theme). You can read more about it here.
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="buttonStyle">#style/DefaultButton</item>
</style>
<style name="DefaultButton" parent="Widget.AppCompat.Button">
<item name="android:textColor">#color/white</item>
</style>
<style name="AllCapsButton">
<item name="android:textAllCaps">true</item>
</style>
layout.xml
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:theme="#style/AllCapsButton"/>
In the code above, button gets the DefaultButton style (white text) applied by the theme, and the AllCapsButton style (capitalized text) applied in the layout file.
You can directly pass style to Button widget in you XML like:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="capitalizedButton"/>
Hope you get the answer. If not please explain your question.

Material design components button global theme overriding broken

I want to simply apply styling to all buttons on a theme level like this
<style name="BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
...
<item name="buttonStyle">#style/DefaultButton</item>
</style>
<style name="DefaultButton" parent="Widget.MaterialComponents.Button">
<item name="android:textColor">#color/whatever</item>
</style>
<Button
android:id="#+id/addChannelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_margin="16dp"
android:text="Add room" />
Why doesnt this work? It would in appcompat
// If I use Theme.MaterialComponents.Light.NoActionBar.Bridge, then it works
You should be setting materialButtonStyle instead of buttonStyle in your theme.
Use a Theme.MaterialComponents theme defining the materialButtonStyle attribute.
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
....
<item name="materialButtonStyle">#style/MyButtonTheme</item>
</style>
In this way you can customize the theme of all the buttons in your app.
Also starting from version 1.1.0 of the material library you can override the theme attributes from the default style using the materialThemeOverlay attribute.
Something like:
<style name="MyButtonTheme" parent="Widget.MaterialComponents.Button">
<item name="materialThemeOverlay">#style/ButtonStyleTextColor</item>
</style>
<style name="ButtonStyleTextColor">
<!-- For filled buttons, your theme's colorPrimary provides the default background color of the component, and -->
<!--the text color is colorOnPrimary -->
<item name="colorOnPrimary">#color/my_color</item>
</style>
Currently it requires version 1.1.0 of material components for android library.
Can you try with v1.0.0-alpha06? There has been some progress since v1.0.0 which may have addressed what you're seeing.
1.1.0-alpha02
Shape Theming: FloatingActionButton, MaterialButton, Chip, MaterialCardView, BottomSheet, & TextInputLayout updated to use the new Material shape system
1.1.0-alpha06
Implement Shapeable interface in MaterialButton
Source: https://github.com/material-components/material-components-android/releases
Use materialButtonStyle and use MaterialButton instead of Button

Styling the popup menu in Android 5.0

I'm making my app ready for Android 5.0, I'm using the latest compatibility library, here is what my style looks like.
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
</style>
</resources>
(The ActionBar color is being set programmatically.)
Now, I want the overflow/popup menu to have the dark background like it had in the holo implementation, but I can't get it to work, here is what it looks like:
I have tried setting the popupMenuStyle but it didn't work.
How can I make the popup menu darker?
Stop using the ActionBar. If you want a ToolBar to be set up like an ActionBar, follow this guide on the android-developers blog.
It actually mentions your use case at Dark Action Bar and provides this code:
<android.support.v7.widget.Toolbar
android:layout_height=”wrap_content”
android:layout_width=”match_parent”
android:minHeight=”#dimen/triple_height_toolbar”
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
Not a full answer but what I found so far:
In past versions you needed to specify a drawable (Check https://github.com/StylingAndroid/StylingActionBar code and tutorials)
Apparently, now that is a color. To modify it you need to do specify the following theme:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
<item name="android:actionBarPopupTheme">#style/popupNew</item>
</style>
<style name="popupNew" parent="android:ThemeOverlay.Material.Light">
<item name="android:colorBackground">#color/red</item>
</style>
</resources>
This works correctly if the theme applied to the app is just this.
If I add android:actionBarPopupTheme to my existing theme, it doesn't work. I am trying to figure out why.
Solved my problem by using this style:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/theme_accent</item>
<item name="colorAccent">#color/theme_accent_secondary</item>
<item name="actionBarStyle">#style/AbStyle</item>
<item name="actionModeBackground">#color/actionmode_bg</item>
</style>
<style name="AbStyle" parent="Widget.AppCompat.Toolbar">
<item name="elevation">2dp</item>
<item name="displayOptions">homeAsUp|showTitle</item>
<!--showHome-->
</style>
<style name="AppThemeDark" parent="Theme.AppCompat">
<item name="colorAccent">#color/theme_accent_secondary</item>
<item name="actionBarStyle">#style/AbStyle</item>
</style>
I had to use Widget.AppCompat.Toolbar as the parent actionBarStyle
Add the property popupTheme to your toolbar:
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/color_primary"
app:theme="#style/Theme.AppCompat.Light"
app:popupTheme="#style/Theme.AppCompat" />
Or define a new style for your toolbar:
<style name="MyToolBarStyle" parent="Widget.AppCompat.Toolbar">
<item name="android:background">#color/green</item>
<item name="popupTheme">#style/Theme.AppCompat.Light</item>
<item name="theme">#style/Theme.AppCompat</item>
</style>
This question has already been answered for styling via XML, but I'm adding an explanation here of how to work out the solution to this and similar styling questions yourself.
First, this is the solution when using AppCompat. To your App's style.xml add actionBarPopupTheme to your theme:
<style name="Theme.MyTheme" parent="#style/Base.Theme.AppCompat.Light.DarkActionBar">
...other stuff here
<item name="actionBarPopupTheme">#style/Theme.MyTheme.ActionBarPopupTheme</item>
</style>
<style name="Theme.MyTheme.ActionBarPopupTheme" parent="#style/ThemeOverlay.AppCompat.Light">
<item name="android:textColor">#android:color/white</item>
<item name="android:background">#android:color/black</item>
</style>
Here's the steps I took to arrive at this solution (it takes a bit of detective work as the Android documentation is poor):
Open your App's style.xml in Android Studio
On the line where you App's theme is defined, put your screen cursor in the parent theme (e.g. click in #style/Base.Theme.AppCompat.Light.DarkActionBar) then press F4. This should take you to the source code for the style in the appcompat library.
Within this style I saw this line:
< item name="actionBarPopupTheme">#style/ThemeOverlay.AppCompat.Light< /item>
This looked like a possible place to change the theme of the popup. I searched for "actionBarPopupTheme" in the poor
Android developers documentation and found "Reference to a theme that should be used to
inflate popups shown by widgets in the action bar". So this was worth playing with.
I copied the appcompat line containing "actionBarPopupTheme" to my style.xml then in this line replaced the item's theme reference (the bit in bold above) with Theme.MyTheme.ActionBarPopupTheme.
In my style.xml I created my new style named Theme.MyTheme.ActionBarPopupTheme. I used the same parent that was used in the style I copied from the appcompat source (the bit in bold above).
To ensure my new popup style was working, I changed the parent style to ThemeOverlay.AppCompat.Dark then ran and tested the code on a device. The popup style changed, so now I knew my overriding of actionBarPopupTheme was the correct thing to do. Then I changed back to ThemeOverlay.AppCompat.Light.
The next challenge is to work out what item names to override in Theme.MyTheme.ActionBarPopupTheme. I changed the text and background colours. To find the correct item names that change the style of something can be tricky in some cases. One way to find less obvious style item names is to look through the style definitions in the appcompat xml file (the one you opened when pressing F4 in the 2nd step above), continually descending into parent styles (F4 again!) until you find something that may do what you want. Google searches will help here too.

EditText Styling

Is it possible to manipulate the style of a text field found in API 17 of android in API 8 ??
The text field in lower API's are very different in comparison with the higher API's. Is there any way to give a uniform look and feel for these components?
To use Android v8 EditText style, change the background of the editText:
android:background="#android:drawable/edit_text"
or use the whole style used in v8:
<style name="Widget.EditText">
<item name="android:focusable">true</item>
<item name="android:focusableInTouchMode">true</item>
<item name="android:clickable">true</item>
<item name="android:background">#android:drawable/edit_text</item>
<item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
<item name="android:textColor">#android:color/primary_text_light</item>
<item name="android:gravity">center_vertical</item>
</style>
Only the EditText? Or do you want every widget to look like pre holo widgets? If so, then setting this as your theme will help:
<application
[...]
android:theme="#android:style/Theme" >
[...]
</application>
However if you just want to have the EditText to be "un-holofied" you can do this:
<EditText
android:id="#+id/spinnermap"
style="#style/MyEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
values/styles.xml:
<style name="MyEditText" parent="android:Widget.Spinner"></style>
and set your Theme to Holo(.Light) and Theme(.Light) for pre HC.
Or if you want to combine everything into one theme with everything except the EditText widget being holo, then you can do this:
values-v11/styles.xml: // v11 because pre HC themes already have the EditText style, you want.
<style name="MyTheme" parent="#android:style/Theme.Holo"
<item name="android:editTextStyle">#style/MyEditText></item>
</style>
Or you can use this:
https://github.com/Prototik/HoloEverywhere
if you want to have Holo on older devices (I mean that you can do it in the opposite way - change old controls to look line new ones). This library also works with ActionBar Sherlock.

Categories

Resources