background issue with styles and themes - android

in attrs I have
<attr name="bzz" format="color" />
then in theme
<style name="mytheme" parent="android:Theme">
<item name="bzz">#color/aaa</item>
</style>
and in the code
this works great
tv.setBackgroundResource(R.color.aaa);
but when I do this it gives me an error
tv.setBackgroundResource(R.attr.bzz);
I do not understand what is the problem, my logic is that I set the bzz as reference to color so that should work fine, but it does not :)
it says like android.content.res.Resources$NotFoundException: Resource ID #0x7f010008
but I do not understand what resource can't be found ?
I am sure that the color is there sins if I set it directly it works great, what exacly is the thing that is not linked correctly
Thanks

You need to resolve the attr to get the corresponding color's resource id. Then you can set the TextView's background resource to the obtained resource id.
Example code:
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.bzz, typedValue, true);
tv.setBackgroundResource(typedValue.resourceId);

Related

How to use a different drawable res folder (for eg. drawable-theme1) when the appTheme is selected as "theme1" from styles.xml? Is this possible?

Currently I am having four themes in my styles.xml file. (theme1, theme2, theme3, theme4).
I am having a test_image.xml in both drawable & drawable-theme1 folders.
What I need is, for theme1 alone, I need resources from drawable-theme1, and for other themes (theme2, theme3, theme4), I need resources from normal drawable folder.
Finally, while setting the image view programmatically, I will be calling imageView.setResource(R.drawable.test_image). The resource file must be retrieved based on my selected theme.
Whether this is possible?
I could not get any questions or similar relevant to this. If anyone has provided a solution already, please help me finding that. Thanks
You can't use <themeName> as a qualifier.
It means that you can't use a drawable-themeName folder.
However you can define a custom attribute in the attrs.xml file:
<resources>
<attr name="myDrawable" format="reference" />
</resources>
Then in styles.xml in the app theme you can define it:
<style name="AppTheme1" parent="Theme.MaterialComponents.DayNight">
<!-- ..... -->
<item name="myDrawable">#drawable/ic_add_24px</item>
</style>
Finally in a layout you can use something like:
<com.google.android.material.button.MaterialButton
....
app:icon="?attr/myDrawable"/>
or programmatically:
MaterialButton button = findViewById(R.id.button);
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.myDrawable, typedValue, true);
button.setIcon(ContextCompat.getDrawable(this,typedValue.resourceId));

How to get an ?attr/ value programmatically

I'm trying to do some custom view styling and I'm having trouble correctly picking up styled attributes from the theme.
For instance, I would like to get the themes EditText's Text Colour.
Looking through the theme stack you can see my theme uses this to style it's EditText's:
<style name="Base.V7.Widget.AppCompat.EditText" parent="android:Widget.EditText">
<item name="android:background">?attr/editTextBackground</item>
<item name="android:textColor">?attr/editTextColor</item>
<item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
</style>
What I'm looking for, is how do I get that ?attr/editTextColor
(Aka, the value assigned by the theme to "android:editTextColor")
Searching through google, I have found enough of this answer:
TypedArray a = mView.getContext().getTheme().obtainStyledAttributes(R.style.editTextStyle, new int[] {R.attr.editTextColor});
int color = a.getResourceId(0, 0);
a.recycle();
But I'm pretty sure I must be doing this wrong as it always displays as black rather than grey?
As commented from #pskink:
TypedValue value = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.editTextColor, value, true);
getView().setBackgroundColor(value.data);
will pull the attribute from the theme currently assigned to the context.
Thanks #pskink!
Have you tried this ?
EDIT :
This is my short answer if you want a complete answer ask me
Your attrs.xml file :
<resources>
<declare-styleable name="yourAttrs">
<attr name="yourBestColor" format="color"/>
</declare-styleable>
</resources>
EDIT 2 : Sorry I forgot to show how I'm using my attr value in layout.xml, so :
<com.custom.coolEditext
android:id="#+id/superEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:yourBestColor="#color/any_color"/>
and then in your custom Editext :
TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.yourAttrs, 0, 0);
try {
int colorResource = a.getColor(R.styleable.yourAttrs_yourBestColor, /*default color*/ 0);
} finally {
a.recycle();
}
I'm not sure if it is the answer what you want but it can put you on good way

Error when getting a dimension in theme for margins

Background
I'm trying to set a custom margin value on the listView items based on the selected theme.
The app has multiple themes, and the user can choose which theme to use , which I set by calling "setTheme()" .
The problem
whatever I try, I get this error:
java.lang.UnsupportedOperationException: Can't convert to dimension: type=0x2
note that this occurs only for the margin attribute, and so far no other attribute has caused this.
What I've tried
first, here's the xml snippets I've used
attrs.xml
<attr name="listview_item__horizontal_spacing" format="dimension" />
styles.xml
<style name="AppTheme_HoloDark" parent="#style/Theme.Sherlock">
<item name="listview_item__horizontal_spacing">4dp</item>
....
the layout of the listView item:
<RelativeLayout ...
android:layout_marginLeft="?attr/listview_item__horizontal_spacing" >
I've also tried using "reference" for the attribute type, and reference to a "dimen" resource, but it also cause the same exception.
Another thing I've tried is getting it dynamically:
public static int getResIdFromAttribute(final Activity activity,final int attr)
{
final TypedValue typedvalueattr=new TypedValue();
activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
return typedvalueattr.resourceId;
}
...
final int spacingResId=getResIdFromAttribute(activity,R.attr.listview_item__horizontal_spacing);
but for some reason I get 0 as the result of this call. Only when using this method it worked.
The question
What is going on? How can I avoid this?
Is there really no way to overcome this but using code (when inflating the xml) ?
You don't need to use attr XML, and this is your issue.
Place your the value you want in a file named dimens.xml in your res folder (same location as strings.xml).
This file will look something like this:
<resources>
<dimen name="value1">15dp</dimen>
<dimen name="value2">20dp</dimen>
</resources>
Then in your layout XML, you can reference the dimen directly (just as you would reference a string), something like this:
<RelativeLayout ...
android:layout_marginLeft="#dimen/value1" >
or when defining a style, in your XML it would look like:
<style name="MyStyle1">
<item name="android:layout_marginLeft">#dimen/value1</item>
</style>
and then for your other style:
<style name="MyStyle2">
<item name="android:layout_marginLeft">#dimen/value2</item>
</style>

Syntax for Retrieving Value from Nested Style Resource?

Since DrawerLayout is part of the chrome of an Android activity, a likely background color for the drawer would seem to be the background color of the action bar, so they match. Hence, I'd like to set up the ListView that is the drawer contents to have the same background color as the action bar, and I'd like to do that in the layout XML that defines the ListView.
And here I get lost in the maze of twisty little passages that is the Android style system...
I know that ?android:attr/ syntax allows you to refer, by reference, to a value defined in the theme being used by the activity (e.g., ?android:attr/activatedBackgroundIndicator as the background for a list item row to work with the "activated" state).
I know that android:actionBarStyle is where a theme points to the style to be used to style the action bar itself, and on that nested(?) style, android:background is the background used for the action bar.
What I don't know is how to craft an ?android:attr/, to be applied to a ListView, that pulls the background from the action bar's defined style.
Is this possible? If so, what's the syntax?
My guess is that this is not possible, which is why the official DrawerLayout sample hard-codes the background color...
Thanks!
It's not possible unfortunately via XML.
You could do the following in code (untested, but should work):
// Need to manually create android.styleable.ActionBar.
// If you need other attributes, add them
int[] android_styleable_ActionBar = { android.R.attr.background };
// Need to get resource id of style pointed to from actionBarStyle
TypedValue outValue = new TypedValue();
getTheme().resolveAttribute(android.R.attr.actionBarStyle, outValue, true);
// Now get action bar style values...
TypedArray abStyle = getTheme().obtainStyledAttributes(outValue.resourceId,
android_styleable_ActionBar);
// background is the first attr in the array above so it's index is 0.
Drawable bg = abStyle.getDrawable(0);
abStyle.recycle();
AFAICT it's simply not possible to use any ?android:attr syntax in order to address actionbar background, simply because there is no such attribute exported in the related attrs.xml
You should add/define such attribute in your custom theme, then use a reference in your styles/layouts. Eg:
-attrs.xml:
<declare-styleable name="CustomTheme">
<attr name="actionbarBackground" format="reference"/>
</declare-styleable>
-themes.xml
<style name="CustomTheme" parent="Theme.Holo.Light">
...
<item name="actionbarBackground">#color/your_fav_color</item>
<item name="android:actionBarStyle">#style/CustomActionbar</item>
...
</style>
-styles.xml
...
<style name="CustomActionbar" parent="#android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">?attr/actionbarBackground</item>
....
</style>

Get a layout set in an attr in attrs.xml and themes.xml

Here's my attr:
<attr name="taskTimePickerLayout" format="reference" />
And here's how it's set in themes.xml:
<item name="taskTimePickerLayout" type="reference">#layout/task_time_picker_holo</item>
I want to inflate a layout using the layout in the attr, how do I do that? I've tried using R.attr.taskTimePickerLayout as the resource for the inflater, but that throws a ResourceNotFoundException.
Put this piece of code into your Activity (or Fragment):
TypedValue typedValue = new TypedValue();
getTheme().resolveAttribute(R.attr.taskTimePickerLayout, typedValue, true);
setContentView(typedValue.resourceId);
Make sure you apply the theme to the Activity before executing this code.
What this code basically does is resolving the reference R.attr.taskTimePickerLayout based on the theme applied to the current Context. typedValue.resourceId is the value of the resolved reference (the layout id of #layout/task_time_picker_holo in this case).
This works also with all other references (drawables, colors etc.)

Categories

Resources