I have two themes that I switch back and forth between in my Android application. In some places, I have TextViews that I want to remain the default color. In other places, I want them to be another color (let's say orange). When changing themes, I'd like only the TextViews that were previously orange to become blue.
Is there a way to do this simply in Android? I had something in mind such as a class tag in html/css but can't seem to find anything.
EDIT: To clarify what I was referring to with the html/css equivalent:
<div>This text is black</div>
<div class="redDiv">This text is red</div>
.redDiv {
color:red;
}
Let's say you have two themes in your application: MyFirstTheme and MySecondTheme:
<style name="MyFirstTheme" parent="android:Theme">
<item name="android:textViewStyle">#style/MyFirstTheme.TextView</item>
[...]
</style>
<style name="MySecondTheme" parent="android:Theme">
<item name="android:textViewStyle">#style/MySecondTheme.TextView</item>
[...]
</style>
The textview styles defined in your styles.xml could look like:
<style name="MyFirstTheme.TextView" parent="#android:style/Widget.TextView">
<item name="android:textColor">#android:color/black</item>
[...]
</style>
<style name="MySecondTheme.TextView" parent="#android:style/Widget.TextView">
<item name="android:textColor">#color/orange</item>
[...]
</style>
<style name="PersistentTheme.TextView" parent="#style/MyFirstTheme.TextView">
<item name="android:textColor">#color/red</item>
</style>
So when you have a layout with two TextViews, you can have the one completely follow the active theme by not setting anything extra to it, and you can apply other appearance to your other TextView instance by specifying a style attribute for it:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- This textview will change text color when other style applied -->
<TextView
android:id="#+id/tv_styledependent"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- This textview will always have the same (red) text color -->
<TextView
android:id="#+id/tv_persistent"
style="#style/PersistentTheme.TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/tv_styledependent" />
</RelativeLayout>
Related
I am developing an app where it will be possible to switch between night and day mode. To do that I want to set theme for ConstraintLayout so it's children will inherit this theme, but they don't...
I mean particularly the TextView color, even if I set the ConstraintLayout theme where textColor attribute is light, the TextView stays dark.
Anyone knows what it is going on? Or I'm doing something wrong?
Theme is described in styles.xml, I've tried setting other two attributes - textAppearance and textViewStyle, none of them work. I've also tried setting this in styles-v21 it didn't work. But when I set this theme directly in TextView, it does work. But I want to avoid spending so much time changing all TextViews manually, also don't want to waste processor time calling findViewById on all views...
This is the parent ConstraintLayout attributes :
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_constraint_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/drawerColorDark"
android:gravity="bottom"
android:theme="#style/AppThemeDark.Drawer">
One of the TextViews :
<TextView
android:id="#+id/drawer_all_articles_text"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginStart="24dp"
android:layout_marginLeft="24dp"
android:gravity="center"
android:text="All Articles"
android:textSize="18sp"
app:layout_constraintStart_toEndOf="#+id/drawer_all_articles_icon"
app:layout_constraintTop_toTopOf="parent" />
And the styles code (not much cause still trying to move forward with inheritance on this example...) :
<style name="AppThemeDark" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
<style name="AppThemeDark.Drawer" parent="AppThemeDark">
<item name="android:textColor">#color/drawerTextDark</item>
<item name="android:textAppearance">#color/drawerTextDark</item>
<item name="android:textViewStyle">#color/drawerTextDark</item>
</style>
<style name="AppThemeDark.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
Many Thanks in advance,
Is there any reason why is textColor property being ignored when it is set via custom textAppearance style?
<style name="EditTextAppearance" parent="#android:style/TextAppearance.Widget.EditText">
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/blue</item> <!-- IGNORED -->
</style>
Setting style in XML:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/EditTextAppearance"
/>
For some reason, default theme control color is not overridden by this style.
The only way how I am able to set color is by setting textColor property in EditText (but this is not what I want):
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/EditTextAppearance"
android:textColor="#color/blue"
/>
Note, custom textAppearance with textColor created for TextView works without problem.
I tried to replace EditText by android.support.v7.widget.AppCompatEditText or android.support.design.widget.TextInputEditText but the result was the same. Still not working. So the problem is not in EditText implementation.
I found question with the same problem Why is textColor in android:textAppearance ignored?. Unfortunately, without answer.
Somewhere along the line, the wrong/default value for textColor is being picked up and applied. You can force the android:textColor that you define in android:textAppearance to be used by setting android:textColor="#null" in your XML for EditText.
android:textColor ignored in android:textAppearance of the EditText because android:editTextColor attribute always overrides text color of the EditText (don ask me why, its about crazy droid).
But all works fine if you add this attribute to your theme:
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:editTextColor">#null</item>
</style>
Still don't know why is textAppearance ignoring textColor when style is created as described in question, but I think I have found another way how to set textColor via style, so somebody might find it useful.
I was playing with EditText colors so I've created custom theme and tried to set editTextColor property, which surprisingly worked:
<!-- consider to extend application theme over default "Base.V7.Widget.AppCompat.EditText" to achieve consistent look and feel -->
<style name="EditTextTheme" parent="Base.V7.Widget.AppCompat.EditText">
<item name="colorControlNormal">#color...</item> <!-- underline color -->
<item name="colorControlActivated">#color...</item> <!-- underline color on focus -->
<item name="editTextColor">#color/blue</item> <!-- ACCEPTED -->
</style>
Setting theme:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="#style/EditTextAppearance"
android:theme="#style/EditTextTheme"
/>
At this moment you have custom "#style/EditTextAppearance" and "#style/EditTextTheme". The good thing is, that you can merge "#style/EditTextAppearance" into the "#style/EditTextTheme" as follows:
<style name="EditTextTheme" parent="Base.V7.Widget.AppCompat.EditText">
...
<item name="editTextColor">#color/blue</item>
<item name="editTextStyle">#style/EditTextAppearance</item>
</style>
This way, you just have to set only theme in your EditText:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/EditTextTheme"
/>
Current solution is almost perfect, but it would be better, if textColor will be set in textAppearance style, so I've tried to remove editTextColor from theme and replace it by textColor property set in textAppearance style #style/EditTextAppearance.
<style name="EditTextAppearance" parent="#android:style/TextAppearance.Widget.EditText">
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/blue</item> <!-- APPLIED if appearance is part of the theme -->
</style>
<style name="EditTextTheme" parent="Base.V7.Widget.AppCompat.EditText">
<item name="colorControlNormal">#color...</item>
<item name="colorControlActivated">#color...</item>
<item name="editTextStyle">#style/EditTextAppearance</item>
</style>
This way textColor contained in textAppearance is finally applied!
I would like to set a default textcolor in my AppTheme, which should be black (not the default Material Design dark grey). The textColor should be overriden by setting a custom style via android:textAppearance-attribute on a UI-element (e.g. TextView).
This is my current setup:
I use AppCompat-Library in my project:
compile 'com.android.support:appcompat-v7:22.2.0'
I defined the following theme:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">#color/primary</item>
<item name="colorPrimaryDark">#color/primary_dark</item>
<item name="colorAccent">#color/accent</item>
<item name="android:textColorPrimary">#color/black</item> <!-- All TextViews should have this color as default text color -->
</style>
which is set in the AndroidManifest.xml:
<application
android:name=".core.BaseApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
Furthermore I defined some styles to change the textAppearance of some TextViews:
<style name="App.Heading" parent="android:TextAppearance.Widget.TextView">
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/red</item>
</style>
<style name="App.Heading.Highlighted" parent="android:TextAppearance.Widget.TextView">
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/blue</item>
</style>
Now I have a xml-layout with some TextViews. Some of them should have the default textAppearance (in fact a black text color as defined as android:textColorPrimary in my theme). Some should apply a custom textappearance from my defined styles:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="CUSTOM: App.Heading"
android:textAppearance="#style/App.Heading" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="CUSTOM: App.Heading.Highlighted"
android:textAppearance="#style/App.Heading.Highlighted" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Normal Textview with no style"/>
The first two TextView apply my defined textAppearance, which is fine. But the last TextView has a dark grey textcolor (Material Design default?) and not a black one. If I set the attribute:
<item name="android:textColor">#color/black</item>
in my AppTheme, all TextViews have a black text color. The textcolor defined in my styles (e.g. App.Heading) is no longer recognized.
So my question is: How can I set a default textColor for my TextViews, which could be overridden by setting a textAppearance?
It is not easy to find the way because there are three styleable android:textColor attributes, textColorPrimary textColorSecondary and textColorTertiary, and a lot of attributes for base styles android:textAppearance as small medium etc (now deprecated?).
Anyway, about TextView without style, it seems that it refers as default to the android:textAppearanceSmall styleable attribute of which value is style TextAppearance.AppCompat.Small that overrides through Base.TextAppearance.AppCompat.Small the android:textColor attribute with ?android:attr/textColorTertiary value.
Then overriding it like the following will work:
<item name="android:textColorTertiary">#color/black</item>
If I remember well, you cannot set the color of the text using the textAppearance. You need to use a style or a theme to achieve this.
Please define following code in style.xml files which are available in v11 ,v14 and v21 folder.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:textColor">#android:color/red</item>
</style>
and use this style for every textview.
I want to change the style of my action bar (change the color and text font) and so set up my manifest and style XML as follows:
Manifest:(application)
android:theme="#style/ArbuckleAppTheme"
Style sheet:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ArbuckleAppTheme" parent="#android:style/Theme.Holo.Light">
<item name="android:actionBarStyle">#style/ActionBarStyle</item>
</style>
<style name="ActionBarStyle" parent="#android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">#color/handler_noorder_startcolor</item>
<item name="android:textColor">#color/handle_noorder_textcolor</item>
</style>
</resources>
The thing is one of my buttons (inside a sliding drawer) becomes much bigger. I tried changing layout values, etc. but to now avail.
Here is the xml surrounding the button:
<Button
android:id="#+id/bCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:text="Cancel"
android:background="#drawable/cancel_singleitem_background"
android:textSize="12dp"
android:padding="5dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"/>
There is an identical button in the main part of my app - which doesn't change shape.
I want to figure out why this one button's shape is getting completely screwed up. Happy to add more code if needed - thought I would start with immediate code first.
I figured it out!
You can remove the parent attribute from the application theme, and this removes the imposition of holo.light formatting across the entire app.
So the code is now:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="ArbuckleAppTheme" >
<item name="android:actionBarStyle">#style/ActionBarStyle</item>
</style>
<style name="ActionBarStyle" parent="#android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">#color/handler_noorder_startcolor</item>
<item name="android:textColor">#color/handle_noorder_textcolor</item>
</style>
</resources>
By the way, the imposition I'm talking about (button becoming bigger) is because Google is trying to impose minimum standards on app development - and that includes buttons that are min. 48px.
I learned a lot from this - hope this is news to some of you so I can give back.
I have created several styles for font in my app.
How can I add these styles to views? - 1) Using style attribute 2) Using textAppearance.
To use style is not an option because views may have other attributes (margins, paddings, min width, etc - I cant specify 2 styles for a view), so I need to specify text-related attributes separately, but android:textColor doesnt work here:
styles.xml:
<style name="TextAppearance.baseText" parent="#android:style/TextAppearance">
<item name="android:textAppearance">?android:textAppearanceSmall</item>
<item name="android:typeface">sans</item>
<item name="android:textColor">#android:color/white</item>
<item name="android:textSize">15sp</item>
</style>
layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="65dp"
android:orientation="horizontal" >
<Button
android:id="#+id/backButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/sometext"
android:textAppearance="#style/TextAppearance.baseText"/>
</RelativeLayout>
Why doesnt it work? How can I specify textcolor in textappearance?
As Oderik has mentioned in the comments, the Button view has a default value for it's textColor attribute. This textColor value overrides whatever value is set through the textAppearance attribute. Therefore you have two options:
Set the textColor to #null in the style:
<style name="Application.Button">
<item name="android:textAppearance">#style/Application.Text.Medium.White</item>
<item name="android:textColor">#null</item>
</style>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/Application.Button" />
Set the textColor to #null in the Button XML:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="#style/Application.Button"
android:textColor="#null" />
It works. Your text color is white - the same as default color. Put there any other color like <item name="android:textColor">#AA6699</item> and you will see difference.
Second thing is that you are trying to set text appearance in text appearance - doen's make sense. If you want to set small letters do this using parent parent="#android:style/TextAppearance.Small and delete line <item name="android:textAppearance">?android:textAppearanceSmall</item>
Third thing is that you want to have small letters and put additional textSize - doesn't make sense.
Try this, works for me:
<style name="BaseText" parent="#android:style/TextAppearance.Small">
<item name="android:typeface">sans</item>
<item name="android:textColor">#AA7755</item>
</style>
If you want to set everything in style:
<style name="BaseText" parent="#android:style/TextAppearance.Large">
<item name="android:typeface">sans</item>
<item name="android:textColor">#AA7755</item>
</style>
<style name="BaseText.Margins">
<item name="android:layout_margin">10dip</item>
</style>
Where BaseText.Margins inherits from BaseText.
Then you can just use:
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
style="#style/BaseText.Margins" />
If you want to use android:TextAppearance instead of style: to set your android:textColor, you need to set android:textColor=#null on your TextView.
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:textAppearance="#style/TextAppearance.AppCompat.Medium.MySubheader"
android:textColor="#null"
tools:text="Section" />
Then it will inherit correctly from your android:TextAppearance
<style name="TextAppearance.AppCompat.Medium.MySubheader">
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/black_54</item>
</style>