I came across code at
HelloGallery Example
ImageAdapter.java - http://developer.android.com/resources/tutorials/views/hello-gallery.html
TypedArray a = obtainStyledAttributes(R.styleable.HelloGallery);
mGalleryItemBackground = a.getResourceId(
R.styleable.HelloGallery_android_galleryItemBackground, 0);
a.recycle();
attrs.xml - http://developer.android.com/resources/tutorials/views/hello-gallery.html
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HelloGallery">
<attr name="android:galleryItemBackground" />
</declare-styleable>
</resources>
and also code at :
Snake Game Example
TileView.java - http://developer.android.com/resources/samples/Snake/src/com/example/android/snake/TileView.html
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TileView);
mTileSize = a.getInt(R.styleable.TileView_tileSize, 12);
a.recycle();
attrs.html - http://developer.android.com/resources/samples/Snake/res/values/attrs.html
<resources>
<declare-styleable name="TileView">
<attr name="tileSize" format="integer" />
</declare-styleable>
</resources>
May I know why they need to get the integer value from XML? Why don't they just code mGalleryItemBackground = 0; and mTileSize = 12;? My guess is that, they want to able to change something without touching Java code. But, I do not see any value being specified explicitly in the XML file itself. A code example to demonstrate the purpose of TypedArray and context.obtainStyledAttributes is very much appreicated.
Both are trying to read an integer. Why one of the example is using getResourceId technique, another is using getInt technique?
I refer to TypedArray JavaDoc, but I can hardly understand what recycle does?
Give back a previously retrieved
StyledAttributes, for later re-use.
May I know why they need to get the integer value from XML? Why don't they
just code mGalleryItemBackground = 0;
and mTileSize = 12;?
I think it's mainly to demonstrate the technique of reading XML attributes from the View constructor, rather than to meet an absolute requirement. If you wanted to re-use your custom view elsewhere (not terribly likely for something as specific as Snake I'll admit) then this is a fantastically useful thing to be able to do... to change the backgound colour etc without having to touch the Java code.
For the tile size in particular, that might be useful to read from XML in case there are different layouts for different device types... you might want different size tiles for different density+size combinations.
Both are trying to read an integer. Why one of the example is using
getResourceId technique, another is
using getInt technique?
Because the gallery background isn't an integer... it's expected to be a resource identifier (such as #drawable/foo). Yes it is still an integer, but an integer whose value isn't known until runtime. The tile size, by contrast, is a constant value and doesn't require any kind of runtime resolving.
I refer to TypedArray JavaDoc, but I can hardly understand what recycle
does?
If in doubt, look at the source. It's basically an optimization to avoid the LayoutInflater having to allocate one of these for every view it inflates.
About styleable attributes
In addition to being able to change that value without touching Java code, it allows them to apply different styles to their app depending on device configuration. Instead of declaring in XML:
<com.example.android.snake.SnakeView
android:id="#+id/snake"
android:layout_width="match_parent"
android:layout_height="match_parent"
tileSize="24" />
they can declare these values in res/values/styles.xml:
<style name="Control.SnakeViewStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="tileSize">24</item>
</style>
and then refer to that style:
<com.example.android.snake.SnakeView
android:id="#+id/snake"
style="#styles/SnakeViewStyle" />
After separating styles like this they can provide different styles.xml file for each device configuration. For example, there might be one res/values/styles.xml for portrait mode and one res/values-land/styles.xml for landscape mode.
About resources and integers
If a styleable attribute is declared as "reference" instead of "integer", you would (1) get IDE content assist when writing XML for that attribute and (2) compiler would check that you haven't provided a reference to non-existing resource. Consequently, to get it you need to use getResourceId, because it may do some additional resolving to get actual resource id.
About recycle
I'm not really sure, but judging by the code of TypedArray, it seems that there's some caching mechanism inside it, and recycle() makes it work.
Related
I was reading Ha Duy Trung's tutorial Supporting multiple themes in your Android app and in it he has the following snippet for values/attrs.xml:
<attr name="themedMenuStoryDrawable" format="reference" />
<attr name="themedMenuCommentDrawable" format="reference" />
Where is this <attr> element actually documented? Looking in the Android API Guide Providing Resources, I cannot find any mention of this type of element.
I did find a mention of <attr> elements in Creating a View Class, but there they all appear inside of <declare-styleable> elements, and there is hardly any explanation of how these elements work.
Is there proper reference documentation for the <attr> element? If not, then:
What does it mean to have an <attr> element directly under <resources>?
What is the meaning of the format attribute, and what values can it take?
What other XML attributes can <attr> take?
Can <attr> appear as the child of anything other than <resources> and <declare-styleable>?
I'd specifically like to know how to use <attr> in the context of theming (rather than custom views) though documentation of how it works in general would be even better.
I'm trying to create a custom attribute for my control. Here's my attrs.xml:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<declare-styleable name="ImageView">
<attr name="testcustom" format="reference"/>
</declare-styleable>
</resources>
In my test app at root, I add this namespace xmlns:TestCustom="http://schemas.android.com/apk/res-auto"
Later in my layout file I have an image view
<ImageView
android:src="#drawable/Icon"
TestCustom:testcustom="#drawable/Icon"/>
The first android:src property is fine, however TestCustom does not work.
The error given is "No resource found that matches the given name (at 'testcustom' with value '#drawable/icon)
So... what's going on here? Anyone have any ideas?
You need to specify your xmlns: to your specific package namespace. For example:
xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews"
Represents custom: for the package namespace of com.example.customviews.
You can read more about this here: https://developer.android.com/training/custom-views/create-view.html#customattr
Note: You may want to consider following the convention of camelCase with regards to your custom attributes, views, etc.
So to recap: The solution here was to use lower case name when referencing the resource via a custom attribute. Apparently Xamarin is doing some work in the background that normally allows resources that start with upper case to be OK, but it probably doesn't address this for custom attributes.
If you are using Xamarin, and custom attributes and you can't reference your resource, try it in lower case!!!
Or as Jon recommends, don't use upper-case stuff at all for resources.
I was looking for how to highlight a selected item in a list when displaying a contextual action bar for the selection, and the solution I found was to set the android:background attribute of my row layout xml to "?android:attr/activatedBackgroundIndicator".
How does setting this work though?
what is the mechanism involved?
what do the syntax elements like "?", "attr", "activatedBackgroundIndicator" mean?
where is the meaning of "activatedBackgroundIndicator" defined?
If you are in a forensic mood here is how to dig and find out what is going on.
android:background="?android:attr/activatedBackgroundIndicator"?
Intuitively this means set the background to some drawable.
But lets decompose this further to see how we get to our mysterious drawable.
To be precise it means "set the background attribute to what the attribute "activatedBackgroundIndicator" refers to in the current theme.
If you understand "refers to in the current theme" part, you have basically understood everything that is going on behind the covers.
Basically, activatedBackgroundIndicator is not an actual drawable but a reference to a drawable. So where is "activateBackgroundIndictor" attribute actually defined?
Its defined in your sdk directory in a file name attrs.xml. For example:
path_to_android_sdk/platforms/android-17/data/res/values/attrs.xml
If you open that file, you will the declaration as follows:
<attr name="activatedBackgroundIndicator" format="reference" />
attrs.xml is where you declare all the attributes that you are later going to use in your view xml. Note we are declaring the attribute and its type and not actually assigning a value here.
The actual value is assigned in themes.xml. This file is located at:
path_to_android_sdk/platforms/android-17/data/res/values/themes.xml
If you open that file, you will see the multiple definitions depending on what theme you are using. For example, here are the definitions for themes name Theme, Theme.Light, Theme.Holo, Theme.Holo.Light respectively:
<item name="activatedBackgroundIndicator">#android:drawable/activated_background</item>
<item name="activatedBackgroundIndicator">#android:drawable/activated_background_light</item>
<item name="activatedBackgroundIndicator">#android:drawable/activated_background_holo_dark</item>
<item name="activatedBackgroundIndicator">#android:drawable/activated_background_holo_light</item>
Now we have our mysterious drawables. If you pick the first one, it is defined in the drawable folder at:
path_to_android_sdk/platforms/android-17/data/res/drawable/activated_background.xml
If you open that file you will see the definition of the drawable which is important to understanding what is going on.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="#android:drawable/list_selector_background_selected" />
<item android:drawable="#color/transparent" />
</selector>
Here we are defining a drawable with two states - default state is just transparent background and if the state is "state_activated" then our drawable is "list_selector_background_selected".
see this link for background information on on drawables and states.
"list_selector_background_selected" is a 9 patch png file that is located in the drawable-hdpi folder.
Now you can see why we defined activatedBackgroundIndicator as a reference rather than linking directly to the drawable file - it allows you to pick the right drawable depending on your theme.
I wondered this as well at one point. A large amount of the Android resources seem to be like a black-box and can't see them directly. I may be missing them someplace, but I can't find them in the SDK source code. Here is what I do know.
android:background will take a drawable.
The syntax is in the style
Must be a reference to another resource, in the form "#[+][package:]type:name" or to a theme attribute in the form "?[package:][type:]name"
In this case the ? signifies to look at a theme in package android and it is of type attr where the name is activatedBackgroundIndicator.
You should be able to access this in the code-behind with android.R.attr.activatedBackgroundIndicator as well.
A list of Android attr properties can be found at R.attr
activatedBackgroundIndicator is a defined drawable in Android 3.0+ as
Drawable used as a background for activated items.
It's basically just a standard item defined in the OS. I can't seem to find in in the Android source, but here is a link to the documentation. activatedBackgroundIndicator
This is a form of attaching a value from a theme. The value is technically not known during resource compilation because the theme values may not be known at that point. Instead the value is resolved at runtime based on the actual theme taken from (most commonly) ContextThemeWrapper.
This provides a way of reusing resource values. I'm not talking performance-wise here, but rather organization and maintenance-wise. The attribute acts as it were a variable with the promise that it will hold an actual value at runtime.
This approach also allows for greater customization - instead of hardcoding the value of e.g. window background drawable it gets the actual drawable from a theme, supplying a chosen attribute as the key. This lets you override the value for that attribute. You simply need to:
Create your own theme (which is just a fancy name for a "style" resource), most commonly deriving from one of default themes.
Supply your own value for the attribute in question.
The platform will automatically use your value provided that you have specified your theme for an activity or application. You do this like described in the question. The general syntax of theme-attribute references is described here: Referencing style attributes. You will also find an example and description of the whole mechanism there.
Edit
One thing that should be noted is the actual attribute names and their existence in various platform versions. It's fairly common for new attributes to be introduced in next platform versions - for example some were added in version 3.0 for the purpose of ActionBar styling.
You should treat attribute names as part of the API - in other words, they are part of the contract you are allowed to use. This is very similar to classes and their signatures - you use LocationManager class for the purpose of obtaining last device location because you know from some source (tutorials, reference, official guides, etc.) what's the purpose of this class. Similarly, the attribute names and their purpose are (sometimes well, sometimes miserably) defined in the Android Platform documentation.
Update: There is a more detailed version available from the API Guide so I'd like to quote it.
A style attribute resource allows you to reference the value of an attribute in the currently-applied theme. Referencing a style attribute allows you to customize the look of UI elements by styling them to match standard variations supplied by the current theme, instead of supplying a hard-coded value. Referencing a style attribute essentially says, "use the style that is defined by this attribute, in the current theme."
To reference a style attribute, the name syntax is almost identical to the normal resource format, but instead of the at-symbol (#), use a question-mark (?), and the resource type portion is optional. For instance:`
Original Answer:
numan salati already offered an perfect answer but it have not addressed the "?" syntax. Here's a quote from API Guide Accessing Resources
To reference a style attribute, the name syntax is almost identical to the normal resource format, but instead of the at-symbol (#), use a question-mark (?), and the resource type portion is optional. For instance:
?[<package_name>:][<resource_type>/]<resource_name>
I need to use a built in value from Android resources. This value is stored com.android.internal.R.attr.listViewStyle. Being unable to get that from within my code, I tried to find the appropriate value I can use insted. Well, I've just found android.R.attr.listViewStyle.
Question 1: Are these values same?
Question 2: Where can I find the XML for com.android.internal.R.attr.listViewStyle? May be I have to create my own style instead that one. In order to find it out I should look at that file.
Sorry if these questions are silly. I'm new to Android development yet.
com.android.internal classes are internal to android, they are only accessible within frameworks.
I think com.android.internal.R.attr.listViewStyle and android.R.attr.listViewStyle are same.
If you want to create your own style you can check here . This contains two listViewStyle. They are used based on the device default theme(Light or dark).
If you want to use this style, then i think you dont need to specify anything in your code, this is default theme, so it is picked automatically, if no attributes are specified.
You can add listViewStyle in values/attr.xml with this code :
<attr name="listViewStyle" format="reference" />
Change com.android.internal.R.attr.listViewStyle in your code to R.attr.listViewStyle
I find it in this
Example for attr.xml
< ?xml version="1.0" encoding="utf-8"?>
< resources>
< attr name="listViewStyle" format="reference" />
</resources>
I'm reading Beginning Android 4 Development and in chapter 5 it talks about Gallery and ImageVievs and introduces the declare-styleable XML tag without explaining its purpose.. I tried to find some info also on the reference, without luck.. For example we have the following:
res/values/attrs.xml
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
<declare-styleable name=”Gallery1”>
<attr name=”android:galleryItemBackground” />
</declare-styleable>
</resources>
example.java
public class GalleryActivity extends Activity {
[...]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery gallery = (Gallery) findViewById(R.id.gallery1);
gallery.setAdapter(new ImageAdapter(this));
[...]
}
[...]
public class ImageAdapter extends BaseAdapter {
[...]
int itemBackground;
public ImageAdapter(Context c) {
context = c;
//---setting the style---
TypedArray a = obtainStyledAttributes(
R.styleable.Gallery1);
itemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
[...]
imageView.setBackgroundResource(itemBackground);
return imageView;
}
}
}
I've read the code a few times and I don't really understand the purpose of defining this styleable Gallery1 with a single attr child only with a name attribute.. can you help me? Is this galleryItemBackground something provided by the system or is it something defined by us? What are we doing in this piece of code?
Thank you in advance for any help!
This tag is part of a set of premade Android attributes defined in R.Styleable, which can be told apart from a custom styleable tag from the android: xml namespace prefix before the attribute name.
This particular attribute is described as:
The preferred background for gallery items. This should be set as the
background of any Views you provide from the Adapter.
You are right, however, that custom attribute tags would require not only the name of the attribute but what its type is, for example adding a custom element to your attrs.xml file might look like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
<attr name=”android:galleryItemBackground” />
<attr name="myCustomAttr" format="string" />
</declare-styleable>
</resources>
Note the lack of the android: namespace on the second attribute as well.
Edit:
Is there any official documentation page that explains in depth this
Styleables?
Check out R.attr (click for link) for various attributes included in Android. You do not need to declare a type for them, because they are all already declared. To know what type has been declared for a particular attribute, find the description for the one you are interested in. galleryItemBackground is, as you may expect, a reference to another resource; other possibilities are booleans, floats, colors, etc.
Additional references: Andtoid uses the <declare-styleable> tag to create an AttributeSet. TypedArray is used to parse the AttributeSet.
If the purpose of the code above [...] is simply get a default
Drawable for the view's background, couldn't I set the variable
itemBackground with getDrawable(android.R.attr.galleryItemBackground)?
In the example, it is hard to see the usefulness of this pattern when there is only one attribute. You can do what you ask, and it may be easier. The construct, however, is part of Android's mantra to separate the UI's "look" from its "functionaly" by letting you set certain attributes in xml instead of having to do everything in code. Take the View class, for example. It has over 30 attributes that can be set in an xml file (size, padding, clickable, focusable, etc); someone making a custom subclass of View can set a few, all or none of these attributes in xml and they are automatically handled for you when the view is created. There are code equivalents to set the attributes if needed, but imagine every time you subclassed View you HAD to set all attributes in code instead of having an option to set them in xml.
It would also be a trivial matter to just make your own resources for your classes that do exactly the same thing, however using the built in styles will provide default resources that match the look and feel of the Android framework if you do not override them.
Hope this helps.