I added a custom attribute to a textview called font. Which automatically loads a custom font.
Example xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.egeniq.widget.TextView
android:layout_width="match_parent"
android:layout_height="44dp"
app:font="MyriadPro"
android:text="#string/login_welcome" />
</RelativeLayout>
The custom widget does the following in its constructors:
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TextView);
String customFont = styledAttrs.getString(font);
// snip. The error occurs here
The R.styleable.TextView is declared as such:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="font" format="string" />
<!-- TextView -->
<declare-styleable name="TextView">
<attr name="font" />
</declare-styleable>
</resources>
When everything is defined as above it works. the variable String customFont is set to the proper name (MyriadPro).
When trying to auto-apply this value trough a style the customFont string is empty.
style is declared as such:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme.BicycleBuddy" parent="android:Theme.Light.NoTitleBar">
<item name="android:textViewStyle">#style/Widget.TextView</item>
</style>
<!-- Override defaults -->
<style name="Widget.TextView" parent="#android:style/Widget.TextView">
<item name="font">MyriadPro</item>
</style>
</resources>
The theme is included in the manifest:
<application
android:name=".Application"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.BicycleBuddy" >
</application>
The <item name="font"></item> gives no errors. The custom widget is loaded and hits the breakpoint. However like said above. if used like this the 'customFont' property is null after reading it.
Screenshots of the stack: The first (where customFont is not null) is where the XML itself includes the app:font="" property. The second, is where it does not include this property, but where it should be loaded from the style
The reason the View element is different is because these are simply 2 different textviews. with the exact same propertys. only 1 includes app:font="" and the other does not. Breakpoints were hit 1 after the other in the order that I would expect.
As you see, virtually everything is equal. Even the ID behind styledAttrs is the same. Yet if it do not explicitly declare the font property in the XML it isn't loaded.
I hope someone directly sees what connection I am missing. but I do realise this is a rather vague issue.
Please note that com.egeniq.* is a custom library attached to my project. The styles.xml is declared in the 'main project', while attrs.xml is from the library project
Related
I would like my application to be available under different brandings - this means that it must be possible to easily change background bitmaps in few places, but also change text resources.
My plan is to use themes and styles, I know they can be used for switching bitmaps but will they allow me to change also texts in TextViews for example?
Is it also possible to specify in style or theme a text identifier and later dynamically read it in code?
[EDIT]
After some investigation, of course texts can be substituted with styles. Another problem that comes with application branding is the need to change package name - otherwise Google Play wont accept our branded application.
[EDIT]
After more investigation, below I include small sample on how to add two switchable themes that will allow to substitude drawable in activity layout, and text resource in textview. Whats left is to call setTheme(R.style.Theme1); or setTheme(R.style.Theme2); in onCreate before setContentView.
<-- attrs.xml />
<resources>
<attr name="ProductName" format="reference"/>
<attr name="ProductBackground" format="integer"/>
</resources>
<-- styles.xml />
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Theme1" parent="android:Theme.Light">
<item name="ProductName">#string/s_product_1_name</item>
<item name="ProductBackground">#drawable/back_1_vga</item>
</style>
<style name="Theme2" parent="android:Theme.Light" >
<item name="ProductName">#string/s_product_2_name</item>
<item name="ProductBackground">#drawable/back_2_vga</item>
</style>
</resources>
<-- my activity layout />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?ProductBackground"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
tools:context=".MainActivity"
android:background="#ff0000"
android:text="?ProductName"
/>
</RelativeLayout>
There are two aproaches to make different brandings of you app:
1) Split your app into multiple library projects, common code is in lets say common_lib library project, and all your brandings are in separate projects using common_lib but changing some of the resources, like strings, some drawables, also package name. This is the aproach we have choosen in our app.
2) Use gradle product flavors: http://developer.android.com/sdk/installing/studio-build.html, I think this should now be the prefered solution.
I'm a using a view flow component into my project, which allows the dev to override some attributes, like that :
<org.taptwo.android.widget.TitleFlowIndicator
...
app:footerTriangleHeight="0dip"
... />
I am reusing this component into several layouts, and I would like to put the properties into a style.
But when I'm doing this, the parser says Error: No resource found that matches the given name: attr 'app:footerTriangleHeight', even if I add the namespace in the styles file.
Is there a way to do that in android ?
Thanks.
Android Application
If you are not using Android Libraries, then here is what you can do:
Define custom styleable attribute (I guess you've already done that).
Do not use your namespace prefix in style items (namespace defaults to current app's namespace).
Example:
In attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="testAttr" format="string"/>
</resources>
In styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TestStyle" >
<item name="testAttr">asdf</item>
</style>
</resources>
Android Library
If custom attribute comes from Android Library, you can still use described approach. It theoretically should work, because Android Library's namespace is the same as application's (from aapt tool perspective during the build). But I haven't test this myself.
If you're specifying namespace, it will show error. As far as I know, styles do not support xml namespaces. So this will fail:
In styles.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:app="http://schemas.android.com/apk/res/app.package.name">
<style name="TestStyle" >
<item name="app:testAttr">asdf</item>
</style>
</resources>
Parser automatically defaults to current app's AndroidManifest namespace, though you can not specify this namespace explicitly.
You can define the style in terms of your namespace, i've used it myself
i.e
<style name="whatever">
<item name="YourPackage.YourSubPackage:parametername">#drawable_or_anything/bla</item>
</style>
I have a few custom views in my Android project and I've added the relevant details to the attrs.xml file. And now I can implement my objects through XML. This works fine.
How do I style these elements? When I try to use my custom attributes in the styles.xml is get an error "No resource found that matches the given name:"
For using the custom views in normal xml developement I use xmlns:app="http://schemas.android.com/apk/res/bla.bla.bla". What is the correct for use in styles?
This is what my style looks like currently
<style name="Journey_DaySelect_Sunday">
<item name="app:onImage">#drawable/day_sunday_selected</item>
<item name="app:offImage">#drawable/day_sunday</item>
</style>
After more intensive searching on Google I gave up finding it answered elsewhere, and by chance tried using the absolute namespace of my generated R file it worked. May this solve all your problems.
USE THE NAMESPACE CONTAINING YOUR R FILE
<style name="Journey_DaySelect_Sunday" parent="Journey_DaySelect">
<item name="AppZappy.NIRailAndBus:onImage">#drawable/day_sunday_selected</item>
<item name="AppZappy.NIRailAndBus:offImage">#drawable/day_sunday</item>
</style>
For clarification, the item's name attribute should be the same as what is in the attrs.xml's declare-styleable name attribute + ":" + the attribute name.
For example:
attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="com.chuck.norris">
<attr name="actionBarTextColor" format="color"/>
</declare-styleable>
</resources>
style.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="myNewStyle">
<item name="android:textColor">#FFFF0000</item>
<item name="com.chuck.norris:actionBarTextColor">#ffff0000</item>
</style>
</resources>
You can then apply this style to all activities by using a theme in your manifest.xml file. Anywhere that a custom view exists that wants to use the "actionBarTextColor" attribute, you can then use the Java code:
TypedArray typedArray = context.obtainStyledAttributes(attrSet, R.styleable.com_chuck_norris);
COLOR_ACTION_BAR_TEXT = typedArray.getColor(R.styleable.com_chuck_norris_actionBarTextColor, 0xff0000ff);
typedArray.recycle();
I'm not sure why you cannot just define your schema in your style.xml file as was asked above, but it seems to be a limitation of style.xml.
try this solution
<style name="Journey_DaySelect_Sunday">
<item name="onImage">#drawable/day_sunday_selected</item>
<item name="offImage">#drawable/day_sunday</item>
</style>
reference(Chinese)
if you guys think it useful,I will translate it.
I have a set of custom Android layout parameters defined in attrs.xml. Now I would like to use some tags in my styles.xml file.
At the moment I get this error:
error: Error: No resource found that matches the given name: attr 'custom:tag'
I have tried declaring custom XML namespace as follows:
<resources
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.my.project"
>
hoping, that the same logic used in every layout declaration can be applied here, but with no success.
The XML namespace mechanism is used to namespace tags and attributes. When you define a style like this:
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.my.project">
<style name="my_style"> <item name="custom:tag">some_value</item> </style>
</resources>
you are trying to apply XML namespacing to an attribute value, which won't work. In this case, you should specify the package name directly, like this:
<style name="my_style"> <item name="com.my.project:tag">some_value</item> </style>
Now Android will be able to resolve where the attribute is defined.
The accepted solution did not work for me, but it shed some light upon the situation.
The custom attributes are resolved and can be referenced in a global project's package name, like "com.ltst.project". Even if you have multiple modules (with the same base package name) the resources would be resolved in a project's package name.
So for me it was enough to just omit any prefixes for custom attributes in a style.
Custom attribute:
<declare-styleable name="SampleView">
<attr name="sample_color" format="reference" />
</declare-styleable>
Style:
<style name="SampleStyle">
<item name="sample_color">#color/sample_color</item>
</style>
You can use the link
xmlns: app = "http://schemas.android.com/apk/res-auto
and define the prefix for each tag as app
To give the user of my app an indication which field currently has the focus I am trying to change the background color of some of my fields depending on the current state, however, I am having troubles understanding Androids Color State List Resources:
I found example (sorry, URL no longer works) and if I try exactly the same, i.e. if I want to adapt the textColor , things do work. However, if I try an only slightly different thing, namely to adapt the background color, things do not work and I don't understand why? Why is this so inconsistent???
To make it simpler to understand what I am trying to do, I append my misc. .xml files:
The AndroidManifest.xml file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mmo.android.test"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".Test"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The Test-Activity:
package mmo.android.test;
import android.app.Activity;
import android.os.Bundle;
public class Test extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
The res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, Test!</string>
<string name="app_name">Test</string>
</resources>
res/color/button_test_color.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#f0f"/> <!-- pressed -->
<item android:state_focused="true" android:color="#ff0"/> <!-- focused -->
<item android:color="#000"/> <!-- default -->
</selector>
and finally my res/layout/main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="foobar"
android:textColor="#color/button_test_color"
android:background="#f00"
/>
<!--
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="foobar"
android:textColor="#f00"
android:background="#color/button_test_color"
/>
-->
</LinearLayout>
If I run this as shown here, it works, i.e. I get a button whose text color changes depending on whether the button is focuses, pressed, etc.
If I uncomment the lower button, where I just flipped the attribute values for textColor and background I get an exception, stating
... <item> tag requires a 'drawable' attribute or child tag defining a drawable
What the heck am I missing here? Why is that color state list acceptable as a text color but not as a background color? How does one specify a view's background color depending on the view's state?
I had this exact problem. It looks to me like android:background doesn't work with Color State Lists. I got around this by creating a State List Drawable instead (individual colors can be used as drawables in the State List).
To use your example, create a file res/drawable/button_test_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#color/pressed_color"/>
<item android:state_focused="true" android:drawable="#color/focused_color"/>
<item android:drawable="#color/default_color"/>
</selector>
Note the use of android:drawable instead of android:color. Android will use the color resource and make a drawable out of it. To finish this off, you need to add the color resources to your res/values/colors.xml file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
...
<color name="pressed_color">#f0f</color>
<color name="focused_color">#ff0</color>
<color name="default_color">#000</color>
...
</resources>
You would then refer to this drawable using #drawable/button_test_background instead of #color/button_test_color.
So, in summary, the Color State List works fine for android:textColor, but for android:background the State List Drawable method above is needed.
The support variant app:background is allowing to use color state lists directly as backgrounds.
For Android 10+, also android:background is working.
Try defining textColor as a drawable, rather than a color:
android:textColor="#drawable/button_test_color"
Resource categories are based on what type of resources they are, not the name of the folder they are located in. XML files of the form button_test_color.xml are typically referenced as "drawable" - I'm actually surprised "color" worked at all!