Defining styles in Android and need to be inheriting from a parent - android

I am a little confused about how I should be writing my styles.
I have written some styles and they appear to work great but I am unsure if I should be inheriting from a style.
For example, by default, a text view (for example) has a default style before applying mine?
So I should be inheriting from something else in my style before applying it, i.e. a halo style?
So, for example, I designed the following style
<style name="TestMe">
<item name="android:textSize">30sp</item>
<item name="android:textColor">#FFFF0000</item>
</style>
Which I have applied to a few text views, seems to work great but should I be doing
<style name="TestMe" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:textSize">30sp</item>
<item name="android:textColor">#FFFF0000</item>
</style>
Inheriting from a parent, if so which one?
If I apply a style to my text view and do not inherit, in effect is the text view losing a lot of styles that were predefined on it before applying my style? I know that I have an app theme that inherits from a parent and this is applied in the androidmanifest.xml. So adding a style doesn't override the theme, which in essence is a style?
Or is inheritance on styles only being used when I want to override something?

Be aware of the precedence order of different styling techniques — if you’re trying to style some text and not seeing the results you expect then your changes are likely being overridden by something higher up in this hierarchy:
Here the whole detail regarding text appearance URL

Related

Applying ThemeOverlay for custom theming a MaterialAlertDialogBuilder dialog

My app theme is set up like this:
<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="colorOnSurface">#color/appColorOnSurface</item>
...
</style>
But when I use MaterialAlertDialogBuilder the text contrast is very poor (because material dialog uses colorOnSurface with 60% alpha, instead of textColorPrimary). So I tried to use this ThemeOverlay:
<style name="ThemeOverlay.App.Dialog.HighContrast" parent="ThemeOverlay.MaterialComponents.Dialog">
<item name="colorOnSurface">#color/appColorOnSurfaceHighContrast</item>
</style>
and applying it like this:
<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="materialAlertDialogTheme">#style/ThemeOverlay.App.Dialog.HighContrast</item>
<item name="colorOnSurface">#color/appColorOnSurface</item>
...
</style>
However, this causes problems when displaying a list of items in the dialog. Each item touch area is limited to the area of text being displayed instead of stretching the width of the dialog like normal.
Furthermore, the theme does not appear to be Material, but rather AppCompat style.
Why does the ThemeOverlay approach cause the unexpected touch area (as if WRAP_CONTENT) issue? Is that not the correct way to apply a ThemeOverlay? Or is there another way to get the alert dialog to use #color/appColorOnSurfaceHighContrast?
I fixed this by using ThemeOverlay.MaterialComponents.MaterialAlertDialog instead of ThemeOverlay.MaterialComponents.Dialog.Alert, and also using materialAlertDialogBodyTextStyle to make sure only the dialog text body was being styled:
<style name="ThemeOverlay.App.Dialog.HighContrast" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="materialAlertDialogBodyTextStyle">#style/MaterialAlertDialog.App.Body.Text.HighContrast</item>
</style>
<style name="MaterialAlertDialog.App.Body.Text.HighContrast" parent="#style/MaterialAlertDialog.MaterialComponents.Body.Text">
<item name="android:textColor">#color/appColorOnSurfaceHighContrast</item>
</style>
But why does AndroidStudio auto-complete only show ThemeOverlay.MaterialComponents.Dialog.Alert and not ThemeOverlay.MaterialComponents.MaterialAlertDialog?
Note: there were actually two issues going on here:
Changing the parent ThemeOverlay from ThemeOverlay.MaterialComponents.Dialog to ThemeOverlay.MaterialComponents.Dialog.Alert fixed the touch area issue, but I was still getting an AppCompat (non-Material) theme.
Changing the parent ThemeOverlay from ThemeOverlay.MaterialComponents.Dialog.Alert to ThemeOverlay.MaterialComponents.MaterialAlertDialog fixed the theme to make it appear Material.
UPDATE: It looks like ThemeOverlay.MaterialComponents.Dialog.Alert is for use with alertDialogTheme and ThemeOverlay.MaterialComponents.MaterialAlertDialog is for use with materialAlertDialogTheme. See: https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/dialog/res/values/themes.xml#L60
However, that still doesn't explain why the latter doesn't auto-complete.

trying to implement toolbar in android

I am trying to get rid of my actiobars and use toolbar to update my app. I am not making my apps for 5.0 yet, so no other material goodness.
From following another post I made my themes.xml look like this:
<style name="AppTheme.Base" parent="Theme.AppCompat">
<item name="colorPrimary">#color/mycolorprimary</item>
<item name="colorPrimaryDark">#color/mycolorprimarydark</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
The first issue I am having is that "Style" is throwing this error:
Element Style must be declared
Theme vs Style
So what exactly is the difference? Well they are both declared in exactly the same way (which you already know), the difference comes in how they’re used.
Themes are meant to be the global source of styling for your app. The new functionality doesn’t change that, it just allows you to tweak it per view.
Styles are meant to be applied at a view level. Internally, when you set style on a View, the LayoutInflater will read the style and apply it to the AttributeSet before any explicit attributes (this allows you to override style values on a view).
Values in an attribute set can reference values from the View’s theme.
Themes are global, styles are local.
From theme-vs-style
I would recomend a read at the above link.

How to define a custom Application theme to specify a default background for a layout in Android?

I am creating a default theme for our Android apps to specify default custom theme to be applied to the whole app. The idea is we shouldn't have to specify appearance related attributes in the layout and they should be automatically injected by applying the custom theme to the entire app.
I am able to do this for UI widgets like TextView and EditText by overriding their styles.
For example overriding android:textViewStyle and android:buttonStyle, etc.
How can I do the same for a layout (LinearLayout or RelativeLayout, etc) so that I can specify a default background for a layout?
The application element in android manifest looks like this:
....
<application android:icon="#drawable/ic_launcher" android:label="#string/app_title" android:allowBackup="false"
android:theme="#style/Theme.MyCustomTheme" android:name="MyAppClass">
Theme.MyCustomTheme looks like this:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.MyCustomTheme" parent="Theme.AppCompat">
<item name="android:textViewStyle">#style/my_custom_text_view_style</item>
<item name="android:editTextStyle">#style/my_custom_edit_text_style</item>
<item name="android:buttonStyle">#style/my_custom_button_style</item>
<item name="android:listViewStyle">#style/my_custom_list_style</item>
The custom styles above inherit from the respective android base styles.
I am looking for the right android attribute to use above to override the style of a layout so that I can apply my custom default background to every layout (LinearLayout or RelativeLayout, etc) declared in the layout xml file without having to explicitly specify it in the layout xml. I tried overriding android:colorBackground but that didn't make any difference. I tried overriding android:windowBackground but that changes the color of the action bar as well. Please note that I am using the appcompat theme from the appcompat support library.
I finally figured out how to define a custom default background for every container layout in my application
First, I defined a a custom theme as a style with the app compat background as the parent background which overrides the default window background. Please note that I am using the theme from the Android compatibility library to support pre-honeycomb Android devices
<style name="Theme.MyCustomAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowBackground">#color/my_custom_window_background</item>
<item name="android:colorBackground">#color/my_custom_window_background</item>
</style>
I applied the above theme to the whole application in the AndroidManifest
<
application android:icon="#drawable/ic_launcher" android:label="#string/app_title" android:theme="#style/Theme.MyCustomTheme"/>
The above steps resulted in every window having my default window background color defined in step 1 above including action bar. I definitely did not want my action bar, edit text, text view etc to be the default window color. So, I needed to to go back to step 1 and override the style of specific UI widgets I did not want to have the default window background
<style name="Theme.MyCustomAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowBackground">#color/my_custom_window_background</item>
<item name="android:colorBackground">#color/my_custom_window_background</item>
<item name="android:actionMenuTextColor">#color/customMenuColor</item>
<item name="android:textViewStyle">#style/customTextViewStyle</item>
<item name="android:editTextStyle">#style/customEditTextStyle</item>
<item name="android:buttonStyle">#style/customButtonStyle</item>
<item name="android:listViewStyle">#style/customListViewStyle</item>
<item name="android:tabWidgetStyle">#style/customTabWidgetStyle</item>
<!-- Support library compatibility -->
<item name="actionBarStyle">#style/customActionBarStyle</item>
<item name="actionMenuTextColor">#color/customMenuColor</item>
The last step was to define the each custom style define above either to have custom styles for them or have then assigned the system default styles (overridden because of custom window background)
For example, the custom action bar style will look like this:
<style name="customActionBarStyle"
parent="#style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">#color/light_black</item>
<item name="android:displayOptions">showHome|showTitle</item>
<item name="android:titleTextStyle">#style/customActionBarTitleTextStyle</item>
<!-- Support library compatibility -->
<item name="background">#color/light_black</item>
<item name="displayOptions">showHome|showTitle</item>
<item name="titleTextStyle">#style/customActionBarTitleTextStyle</item>
</style>
The advantage of this approach is you can define a default theme in a centralized way and don't have to define a background for each layout as it will be injected through the custom theme applied to the entire app.. Any future re-theming of the app will be very easy with this approach
Please refer to the Android Documentation on theming including how to theme the action bar for more information
Looking at themes.xml i didn't see anything applicable to layouts and ViewGroups in general, (although there are styles support for lists and some widgets as you can see).
Therefore I am not sure that it is possible to have your custom style applied to all layouts.
I guess you would still have to apply your custom layout style, (where you could change background color as
<item name="android:background">#ff0000</item>
) to each of your layouts yourself.
Feel free to prove me wrong.

Android cascading layouts?

Is there a way to specify different styles for different elements of a view group within one style?
For example, I have a list where each item has a title, details and separator. I would like to be able to have one style tag in my styles.xml that applies side padding to the text but only top/bottom padding to the separator.
I realise my thinking could be influenced by css, I was just wondering if there was an elegant solution in android for it.
A style can have a parent, with the resulting view applying attributes "top-down", i.e. the child styles will override conflicting parent style attributes.
Code I ended up using (I have a list with multiple separators, I wanted padding only on the last one):
<style name="ListItemSeparator">
<item name="android:background">android:attr/listDivider</item>
<item name="android:layout_height">1px</item>
</style>
<style name="LastListItemSeparator" parent="ListItemSeparator">
<item name="android:layout_marginBottom">20dp</item>
</style>
More info can be found here
If it's just your own styles you want to extend, then you can use the dot notation, as mentioned in the Android docs, i.e. you could do:
<style name="ListItemSeparator">
<item name="android:background">?android:attr/listDivider</item>
<item name="android:layout_height">1px</item>
</style>
<style name="ListItemSeparator.LastListItemSeparator">
<item name="android:layout_marginBottom">20dp</item>
</style>
Then reference the style like:
<View style="#style/ListItemSeparator.LastListItemSeparator"/>
You can subclass a View in java and then refer to it in your xml.
Then, you can subclass your custom View to create views that inherit from it.

android: How can I define custom colors, drawables, etc. in themes?

I hope I can explain what I'm after. In essence, my users have asked me to allow different looks in my application, which I hope I can do with themes.
I hoped I could do something like this:
<style name="NewTheme" parent="android:Theme.Dark">
<item name="labelColor">#f90</item>
<item name="buttonColor">#fff</item>
<item name="buttonBg">#drawable/button</item>
</style>
<style name="OldTheme" parent="android:Theme.Dark">
<item name="labelColor">#fa0</item>
<item name="buttonColor">#88f</item>
<item name="buttonBg">#drawable/button_old</item>
</style>
And then reference these values in my styles.xml:
<style name="labelStyle">
<item name="android:textColor>#labelColor</item>
</style>
<style name="buttonStyle">
<item name="android:textcolor">#buttonColor</item>
<item name="android:background">#buttonBg</item>
</style>
I know this syntax is wrong, but what might be the right syntax? Basically, I want to create sets of attributes (color, background, a couple other things) and select them based on theme.
To work with themes and styles in Android you have to:
Define one or more themes in themes.xml and set the definitions of
your styles there.
Define custom attributes, a.k.a. custom styles, in attrs.xml.
Describe what the values of your custom styles are in styles.xml.
In your layout files, give your views a style attribute, which has a
custom style name as their values.
Set the theme of your application or activity in either
AndroidManifest.xml or in the Activity's onCreate(). This is done by calling setTheme() in the activity's onCreate() method, before any call to setContentView().
To change the theme, you simply need to restart your activity.
Iadvice you to look at this tutorial it deals with all that a programmer want to work on android themes (text color, text formatting, state list drawable etc ...)

Categories

Resources