Setting a style on an individual view does not work - android

I'm having trouble setting a theme on individual views in one of my activities.
Setting the theme in the application tag in my manifest works perfectly, as does setting the theme in the activity tags in the manifest.
Regardless of whether I have a theme set in the manifest or not, if I try and set a theme on an individual view:
<TextView
android:id="#+id/userFullNameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"
android:layout_toRightOf="#+id/profileImageView"
android:text="Bobby Joe"
android:textAppearance="?android:attr/textAppearanceMedium"
android:theme="#style/Theme.Sherlock.Light" />
the view always appears with either the default theme (nothing set in manifest) or the same theme specified in the manifest.
I'm not overriding the Theme.Sherlock.Light theme anywhere in my xml files. I've tried several different combinations of themes to no avail. Oh, and I'm obviously using ActionBarSherlock.
EDIT
If I create a new style:
<style name="SideMenuStyle" parent="Theme.Sherlock.Light" >
</style>
and use this style in my xml, it still does not display the correct style.

There's no android:theme xml attribute defined for views. You can use style xml attribute instead, but you have to reference a style for the view instead of the whole theme.
Use it like this:
<TextView
android:id="#+id/userFullNameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"
android:layout_toRightOf="#+id/profileImageView"
android:text="Bobby Joe"
android:textAppearance="?android:attr/textAppearanceMedium"
style="#style/MyTextViewStyle" />
Note that you can also define a default theme for all instances of TextView or any other widget within the scope of a theme. For TextView that would mean to define android:textViewStyle in the theme:
<style name="MyTheme" parent="#style/Theme.Sherlock">
<item name="android:textViewStyle">#style/MyTextViewStyle</item>
</style>

Related

Change theme for button programmatically

I can able to set theme to button using android:theme attribute in xml. Is there any equivalent programmatical code?
<Button
android:id="#+id/btnPayment"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:text="Add Payment"
android:theme="#style/ButtonPeter" // theme..
/>
style.xml
<style name="ButtonPeter" parent="Widget.AppCompat.Button">
<item name="colorButtonNormal">#color/fbutton_color_peter_river</item>
<item name="android:textColor">#android:color/white</item>
</style>
Can I able to set theme dynamically using something like this btnPayment.setTheme(R.style.ButtonPeter) ?
I search a lot but all posts are related to set style or create dynamic button and apply style to it but I dont want to do that .I want to set theme to button
How to achieve this?
I think you are confused with style and theme. From this document, it says: theme for the whole activity while style is for view.
A style is a collection of properties that specify the look and format for a View or window.
A theme is a style applied to an entire Activity or application, rather than an individual View.
For this code:
android:theme="#style/ButtonPeter" // theme is used but only valid style attributes for button will be applied
Hope this help.
As I mention here, using TextViewCompat.setTextAppearance should work :-)

How to explore styling in android

I'm trying to theme my app in Android. However, each widget is an excrutiating pain in itself: I have to search for theming that particular widget and then create a style that hopefully derives from same style that widget uses.
Of course, answers about theming a particular widget don't always contain info about base style, just the particular colors.
So, instead of accepting fish to eat, can you teach me to fish instead?
How do I interpret those ObtainStyledAttributes() calls in widget constructors and extract styles from that? How do I recurse that?
In particular, can you walk me through AlertDialog button color? What style defines lollipop flat button + teal text color? How do I get to that style if I start from AlertDialog source and ObtainStyledAttributes call?
I find that styling is about sherlocking your way through the framework. The what (almost always) comes from the widget's implementation. The where, I find is all over the place. I will try my best to explain the process through your particular use-case - AlertDialog's button(s).
Starting off:
You already have this figured out: we start with the widget's source code. We are specifically trying to find - where AlertDialog buttons get their text-color. So, we start with looking at where these buttons come from. Are they being explicitly created at runtime? Or are they defined in an xml layout, which is being inflated?
In source code, we find that mAlert handles the button options among other things:
public void setButton(int whichButton, CharSequence text, Message msg) {
mAlert.setButton(whichButton, text, null, msg);
}
mAlert is an instance of AlertController. In its constructor, we find that the attribute alertDialogStyle defines the xml layout:
TypedArray a = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.AlertDialog,
com.android.internal.R.attr.alertDialogStyle, 0);
mAlertDialogLayout =
a.getResourceId(
com.android.internal.R.styleable.AlertDialog_layout,
com.android.internal.R.layout.alert_dialog);
So, the layout we should look at is alert_dialog.xml - [sdk_folder]/platforms/android-21/data/res/layout/alert_dialog.xml:
The layout xml is quite long. This is the relevant part:
<LinearLayout>
....
....
<LinearLayout android:id="#+id/buttonPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="54dip"
android:orientation="vertical" >
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="4dip"
android:paddingStart="2dip"
android:paddingEnd="2dip"
android:measureWithLargestChild="true">
<LinearLayout android:id="#+id/leftSpacer"
android:layout_weight="0.25"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone" />
<Button android:id="#+id/button1"
android:layout_width="0dip"
android:layout_gravity="start"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:maxLines="2"
android:layout_height="wrap_content" />
<Button android:id="#+id/button3"
android:layout_width="0dip"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:maxLines="2"
android:layout_height="wrap_content" />
<Button android:id="#+id/button2"
android:layout_width="0dip"
android:layout_gravity="end"
android:layout_weight="1"
style="?android:attr/buttonBarButtonStyle"
android:maxLines="2"
android:layout_height="wrap_content" />
<LinearLayout android:id="#+id/rightSpacer"
android:layout_width="0dip"
android:layout_weight="0.25"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone" />
</LinearLayout>
We now know that the buttons get the style held by attribute buttonBarButtonStyle.
Head over to [sdk_folder]/platforms/android-21/data/res/values/themes.material.xml and search for buttonBarButtonStyle:
<!-- Defined under `<style name="Theme.Material">` -->
<item name="buttonBarButtonStyle">#style/Widget.Material.Button.ButtonBar.AlertDialog</item>
<!-- Defined under `<style name="Theme.Material.Light">` -->
<item name="buttonBarButtonStyle">#style/Widget.Material.Light.Button.ButtonBar.AlertDialog</item>
Depending on what your activity's parent theme is, buttonBarButtonStyle will refer to one of these two styles. For now, let's assume your activity's theme extends Theme.Material. We'll look at #style/Widget.Material.Button.ButtonBar.AlertDialog:
Open [sdk_folder]/platforms/android-21/data/res/values/styles_material.xml and search for Widget.Material.Button.ButtonBar.AlertDialog:
<!-- Alert dialog button bar button -->
<style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Colored">
<item name="minWidth">64dp</item>
<item name="maxLines">2</item>
<item name="minHeight">#dimen/alert_dialog_button_bar_height</item>
</style>
Okay. But these values don't help us in determining the button's text color. We should look at the parent style next - Widget.Material.Button.Borderless.Colored:
<!-- Colored borderless ink button -->
<style name="Widget.Material.Button.Borderless.Colored">
<item name="textColor">?attr/colorAccent</item>
<item name="stateListAnimator">#anim/disabled_anim_material</item>
</style>
At last, we find the textColor - and its supplied by attr/colorAccent initialized in Theme.Material:
<item name="colorAccent">#color/accent_material_dark</item>
For Theme.Material.Light, colorAccent is defined as:
<item name="colorAccent">#color/accent_material_light</item>
Browse to [sdk_folder]/platforms/android-21/data/res/values/colors_material.xml and locate these colors:
<color name="accent_material_dark">#color/material_deep_teal_200</color>
<color name="accent_material_light">#color/material_deep_teal_500</color>
<color name="material_deep_teal_200">#ff80cbc4</color>
<color name="material_deep_teal_500">#ff009688</color>
Screenshot of an AlertDialog and the corresponding text-color:
Shortcut:
Sometimes, its easier to read the color value (as in the picture above) and search for it using AndroidXRef. This approach would not have been useful in your case since #80cbc4 would have only pointed out that its the accent color. You would still have to locate Widget.Material.Button.Borderless.Colored and tie it with attribute buttonBarButtonStyle.
Changing button's text-color:
Ideally, we should create a style that extends Widget.Material.Button.ButtonBar.AlertDialog, override android:textColor inside it, and assign it to attribute buttonBarButtonStyle. But, this won't work - your project won't compile. This is because Widget.Material.Button.ButtonBar.AlertDialog is a non-public style and hence cannot be extended. You can confirm this by checking Link.
We'll do the next best thing - extend the parent style of Widget.Material.Button.ButtonBar.AlertDialog - Widget.Material.Button.Borderless.Colored which is public.
<style name="CusButtonBarButtonStyle"
parent="#android:style/Widget.Material.Button.Borderless.Colored">
<!-- Yellow -->
<item name="android:textColor">#ffffff00</item>
<!-- From Widget.Material.Button.ButtonBar.AlertDialog -->
<item name="android:minWidth">64dp</item>
<item name="android:maxLines">2</item>
<item name="android:minHeight">#dimen/alert_dialog_button_bar_height</item>
</style>
Note that we add 3 more items after overriding android:textColor. These are from non-public style Widget.Material.Button.ButtonBar.AlertDialog. Since we cannot extend it directly, we must include the items it defines. Note: the dimen value(s) will have to be looked up and transferred to appropriate res/values(-xxxxx)/dimens.xml files(s) in your project.
The style CusButtonBarButtonStyle will be assigned to attribute buttonBarButtonStyle. But the question is, how will an AlertDialog know of this? From the source code:
protected AlertDialog(Context context) {
this(context, resolveDialogTheme(context, 0), true);
}
Passing 0 as the second argument for resolveDialogTheme(Context, int) will end up in the else clause:
static int resolveDialogTheme(Context context, int resid) {
if (resid == THEME_TRADITIONAL) {
....
} else {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(
com.android.internal.R.attr.alertDialogTheme,
outValue, true);
return outValue.resourceId;
}
}
We now know that the theme is held by alertDialogTheme attribute. Next, we look at what alertDialogTheme points to. The value of this attribute will depend on your activity's parent theme. Browse to your sdk folder and find the values/themes_material.xml inside android-21. Search for alertDialogTheme. Results:
<!-- Defined under `<style name="Theme.Material">` -->
<item name="alertDialogTheme">#style/Theme.Material.Dialog.Alert</item>
<!-- Defined under `<style name="Theme.Material.Light">` -->
<item name="alertDialogTheme">#style/Theme.Material.Light.Dialog.Alert</item>
<!-- Defined under `<style name="Theme.Material.Settings">` -->
<item name="alertDialogTheme">#style/Theme.Material.Settings.Dialog.Alert</item>
So, based on what your activity's base theme is, alertDialogTheme will hold one of these 3 values. To let AlertDialog know of CusButtonBarButtonStyle, we need to override attribute alertDialogTheme in our app's theme. Say, we're using Theme.Material as the base theme.
<style name="AppTheme" parent="android:Theme.Material">
<item name="android:alertDialogTheme">#style/CusAlertDialogTheme</item>
</style>
From above, we know that alertDialogTheme points to Theme.Material.Dialog.Alert when your app's base theme is Theme.Material. So, CusAlertDialogTheme should have Theme.Material.Dialog.Alert as its parent:
<style name="CusAlertDialogTheme"
parent="android:Theme.Material.Dialog.Alert">
<item name="android:buttonBarButtonStyle">#style/CusButtonBarButtonStyle</item>
</style>
Result:
So, instead of accepting fish to eat, can you teach me to fish
instead?
In the very least, I hope to have explained where the fish are.
P.S. I realize I have posted a mammoth.
Besides #Vikram excellent answer, it's worth noting that Android Studio can simplify your work enormously. You just need to hover your mouse over the Theme, it will show something like following.
actionBarStyle = #style/Widget.AppCompat.Light.ActionBar.Solid
=> #style/Widget.AppCompat.Light.ActionBar.Solid
You can also use mouse click to navigate between styles, like what you do with normal java code.
And you can find support library's res in
<sdk root>/extras/android/m2repository/com/android/support/<support library name>/<version number>/<support library>.aar/res
But the *.aar/res/values/values.xml contains all values, and it's not easy to read. You can get the original support library code and resources in
https://android.googlesource.com/platform/frameworks/support/+/master
There is a button named tgz to download current snapshot.

Android - use attributes to tweak custom styles

here's my issue. I have defined custom themes and styles, so as to customize various Views, in the relevant .xml files. Here are some code extracts:
themes.xml:
...
<style name="Legacy" parent="android:Theme.NoTitleBar">
<item name="android:buttonStyle">#style/Legacy.Button</item>
...
</style>
styles.xml:
...
<style name="Legacy.Button" parent="#android:style/Widget.Button">
<item name="android:textColor">#ffffff</item>
<item name="android:background">#drawable/button_selector_blue</item>
<item name="android:textSize">15dp</item>
</style>
Let's say I set my application's theme to Legacy. If I use a Button in a layout, it will get my custom default parameters (white text, background is #drawable/button_selector_blue, etc).
Now let's say I want to keep those parameters save for the text size: I'd like to have some buttons with a larger text size, which would be defined in an titleSize attribute in attrs.xml:
...
<attr name="titleSize" format="reference|dimension" />
and which value is set for each theme in my themes.xml file.
So my layout would contain something like:
<Button
android:id="#+idmyButtonId"
android:drawableRight="#drawable/aDrawable"
android:text="#string/someText"
android:textSize="?titleSize"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</Button>
When launching my app I get the following error:
java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x2
So it seems I cannot tweak custom styles using attributes - at least not this way. Is such a thing possible ? If not, what would you use to achieve such a result ?
I'd like to give the user the ability to select among different themes, so I can't just define an additionnal ButtonWithLargeText style and directly use it in my layout.
Thanks for your help !
I finally got it to work. Instead of defining my titles' size in attrs.xml, I used dimens.xml. So now the following works:
<Button
android:id="#+idmyButtonId"
android:drawableRight="#drawable/aDrawable"
android:text="#string/someText"
android:textSize="#dimen/titleSize"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</Button>
While I get my regular text size (which I defined in my styles.xml) on the Button by using this:
<Button
android:id="#+id/idRegularButton"
android:text="#string/regularSizeText"
android:layout_width="wrap_content" android:layout_height="wrap_content">
</Button>

applying themes to my android app dynamically

I have three buttons to change themes. On clicking each button my app theme must change dynamically. How to do it programmatically.
To set the theme dynamically at runtime, call setTheme() in your activity's onCreate() method, before calling setContentView(). To change the theme, you simply need to restart your activity.
Here is a nice tutorial on how dynamically apply themes.
and this one too.
Please Visit this link for it.
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="#string/hello" />
<TextView
style="#style/CodeFont"
android:text="#string/hello" />
By defining an xml theme file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CodeFont" parent="#android:style/TextAppearance.Medium">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style>
</resources>
You can also apply styles to all activities of an application:
<application android:theme="#style/CustomTheme">
Or just one activity:
<activity android:theme="#android:style/Theme.Dialog">
Sorry but you can't change styles programmatically.
how to set the Style Attribute Programmatically in Android?
There are certainly other methods to achieve this desired behavior however. You could set onclick listeners for each button, and programmatically change text size, color, background etc of your various view elements
you can use a particular theme for a given xml file.
in graphical layout you can CHANGE the theme of the layout using editing config.
use onclick event to go to next layout and here your theme will be different from the first one.
Vimalatha, to change your background when you click a button just add this code to the onClick function of your button.
myLinearLayout.setBackgroundColor(Color.BLUE);
Assuming that myLinearLayout is your LinearLayout name...

TextAppearance in theme

I want to set the text appearance in my theme to be TextAppearnance.Large.
Here is what I am doing in my styles.xml (my application is pointing to this theme in my manifest)
<style name="myTheme" parent="android:Theme.NoTitleBar.Fullscreen">
<item name="android:textAppearance">#android:style/TextAppearance.Large</item>
</style>
Problem:
My text is still being displayed small.
Question(s):
What am I doing wrong in trying to use a predefined TextAppearance in my activity? i.e. How do specify this TextAppearance correctly?
Where are the TextSizes for TextAppearance.Large/Medium/Small defined?
First, declare the attribute as
<item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
But declaring text appearance or text color in a theme only affects text that has absolutely no style or attribute anywhere, including system-defined ones. If you add a
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Medium Text" />
without even the android:textAppearance="?android:attr/textAppearanceMedium" line that Eclipse throws in, it will be affected by this theme, but buttons and the like never will.
themes and styles are defined in the themes.xml and styles.xml files of the sdk implementations in your environment (distinct ones for different android versions or sdk levels).
search your computer for themes.xml (you will probably find multiple instances of it in the "program files/android" folder on a windows 32-bit machine, for example).
this post explains how to customize these attributes.
you can also set explicit size attributes in your xml layout file, by modifying the TextView tag attributes:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="15sp is the 'normal' size."
android:textSize="15sp"
/>
this post explains how to customize android fonts (including fontType, fontColor, shadow, bold, italic) directly in xml layout file.

Categories

Resources