Where is the documentation for Android resource XML's `<attr>` element? - android

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.

Related

Xamarin custom attribute of reference type does not work

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.

Required custom attributes

android:layout_width and android:layout_height are required attributes, i.e. if you don't specify them for a Layout, Android Studio tells me "Element x doesn't have required attribute android:layout_height."
I'm defining some custom attributes in my own classes and I'd like to require that anyone who uses them in xml specify values just like they have to specify layout_width and layout_height.
How do I do that? Is there something I can add in attrs.xml here:
<declare-styleable name="MyStyleable">
<attr name="myAttribute" format="float"/>
</declare-styleable>
Or maybe in style.xml here:
<style name="MyStyle">
<item name="myAttribute">3</item>
</style>
AFAIK, currently attrs don't have any attributes to mark them mandatory. ("layout_width" and the like are very common mistakes, checking for those is wired into the SDK)
You can, however, throw an RuntimeException from your custom View if an attribute is missing (which you can determine by calling TypedArray.hasValue()) -- TypedArray does that in getLayoutDimension() method.
This is exactly the behavior you get if you compile an app that's missing a "layout_width" somewhere using command line tools (i.e. no Eclipse or Idea to detect the missing atrribute and prevent you from compiling): you run the app and it crashes immediately with a RuntimeException saying you're missing the attribute.
Using Android KTX, there are extension functions that provide getFloatOrThrow() and other similar methods.
Check them out here
TypedArray also has a few methods to cover both attribute getting and exception throwing states. Just use them if you want your attribute to be required (not clearly)
Try to take a look at this link. There is info about how is "wrap_content" and "match_parent" defined. Maybe this will help.

finding resources of view

I'm trying to add to my project the source code of SlidingDrawer, I could find it easily in grepCode.
The problem is that the code is not compiling, there's references to native resources, for Ex.
R.styleable.SlidingDrawer_orientation
that I'm cannot find, neither in GrepCode nor in Android repositories at GitHub.
does anyone have encountered in such a scenario and was managed to solved it?
Thanks.
So I just tried doing this, I had compile errors related to the resources as well. Those resources are not publically available to android.R. As the previous answerwer said, some resources are declared internal/hidden.
Once I imported my own frameworks_all.jar file I was able to see them and even build my own little SlidingDrawer class, with no more work than just copying the file into my own project.
This is an excellent guide to get you started on understanding the concepts of / getting used to using Android's hidden and internal classes:
Amazing Super Awesome Guide to Android's Internal / Hidden API which will totally work and make your life better
Note The attributes appear to be hidden, not internal, so you just need to worry about getting access to hidden components.
A bit of background if you are interested though, the resource file for android (android.R) gets compiled specially in frameworks/base. The attribute you want doesn't appear to exist on it's own, I.E. there is no xml file in frameworks base where R.styleable.SlidingDrawer_orientation exists. That's why you couldn't just find it. There IS however, an attribute file: frameworks/base/core/res/res/values/attrs.xml which you can find the orientation listed as an attribute for:
<!-- SlidingDrawer specific attributes. These attributes are used to configure
a SlidingDrawer from XML. -->
<declare-styleable name="SlidingDrawer">
<!-- Identifier for the child that represents the drawer's handle. -->
<attr name="handle" format="reference" />
<!-- Identifier for the child that represents the drawer's content. -->
<attr name="content" format="reference" />
<!-- Orientation of the SlidingDrawer. -->
<attr name="orientation" />
...
Seems like android marks all the styleable attributes hidden because the entire section is obscured from public code. I'm not sure of the specifics in how this R file gets constructed, I'd have to dig more into make files to find out. Either way, end fluff, to reiterate all you need to do is get access to the internal/hidden components.
The R file is auto generated based on the resource files you have under the folder /res
Read more about it: http://developer.android.com/guide/topics/resources/providing-resources.html
So in this case, you don't have a resource defined for SlidingDrawer_orientation...try to look for the corresponding resource under the /res folder from the project you are copying from. Some resources from the Android OS library are declared internal/private...therefore you can't really access them in your code, what you could do is replicate if you have the proper resources.

Do com.android.internal.R.attr and android.R.attr have the same set of values?

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>

Usage of TypedArray in Android Application

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.

Categories

Resources