Typically I have to write layout code like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" />
I want to do something like this:
<LinearLayout xmlns="http://schemas.android.com/apk/res/android"
layout_width="fill_parent"
layout_height="fill_parent"
orientation="vertical" >
But this code doesn't run properly. Why?
And second question: Why element namen are in CamelCase and attributes are in under_score?
XML default namespaces do not apply to attribute names. Hence, you always have to specify the namespace of an attribute, if it has one:
Default namespace declarations do not
apply directly to attribute names; the
interpretation of unprefixed
attributes is determined by the
element on which they appear.
So the real question is: Why did the Android designers define the element names without a namespace, putting only the attributes into the Android namespace?
As the document suggests, if the element names were in the Android namespace, then attribute names really wouldn't need their own namespace.
But this code doesn't run properly. Why?
Because the build tools do not support it. Last I checked, any prefixed namespace should work (e.g., xmlns:a="http://schemas.android.com/apk/res/android"), but the default namespace has never worked.
If you wish, you can propose and contribute a patch. Along the way, you will be able to determine whether or not there is a philosophical reason for this, a technical reason, or if they just never got around to it.
Why element namen are in CamelCase and attributes are in under_score?
Element names are Java classes, which are typically in CamelCase. Attributes are not "in under_score" in general -- the layout_ prefix indicates a family of attributes that are requests from a View to its container. But, if you look at the attributes more carefully, you will see that most are camelCase, ignoring this prefix (e.g., android:textSize).
Related
I've read (and confirmed with testing) that resource value names (Strings, Drawables, dimensions, etc.) should have a prefix at the beginning (generally the library's name) to avoid name conflicts, because a project that uses the library and declares a resource with a matching name will overwrite the library's resource.
What I'm unclear on is whether the names of attr attributes inside a <declare-styleable> should also be prefixed. Since they are wrapped within the <declare-styleable>, are they protected from over-writing? Within Java code, their resource names are automatically prefixed with the name of the <declare-styleable>, but when used within XML files, they are not.
I'm guessing that their usage is context sensitive. That in my custom Preference's code, when I call context.obtainStyledAttributes() with a specific styleable, it is only at that point that the XML attributes are interpretted as specific types. If I declare a Preference styleable attribute named "min" of type float and use it in my project, it will not matter that there is an attribute named "min" in the v7.preference library's SeekBarPreference styleable of type int, because SeekBar doesn't use my styleable when calling obtainStyledAttributes().
So if my assumption is correct, there's no reason the compiler would be consolidating attributes by name like that. But custom attribute styling is a complex beast in Android, and I'm not sure if I'm missing something in my testing. It would be nice to omit the prefixes in my library's attribute names for ease of use/documentation.
If the <declare-styleable> is defining attributes for a Style, then I think it's still safe from conflicts, because Styles don't merge. They only reference each other from their own attributes. If I understand them correctly--they are somewhat convoluted to me.
On a related note, is there any reason view IDs should be prefixed? I'm thinking yes, because my library view exists within a project's view structure and a user of the library calls findViewById() on an ID that matches one of mine, I could envision scenarios where the search turns up my view first and trips them up. But Google's own appcompat libraries take no such precaution, so I'm unsure.
After studying documentation and AOSP source code, I've come to the conclusion that yes, you should prefix attribute names.
Resource attributes are not <declare-styleable> local. They are all global. When you declare a resource attribute (which can be done inside or outside of a <declare-styleable>), you name it and give it a format type:
<attr name="my_attribute" format="string" /> <!-- This is a declaration -->
When you reference a resource attribute (which is only done from within a <declare-styleable>), you list its name but not its format.
<attr name="my_attribute" /> <!-- This is a reference -->
Lint shows an error if you try to declare two attributes with the same name.
The fact that you can declare an attribute from within a <declare-styleable> is merely a convenience for code conciseness. It does not imply a limited scope. If you are planning to use the same attribute in multiple styleables, it's probably good practice to put its declaration outside of any <declare-styleable>, so it can be found easily.
One oddity I've noticed is that Lint doesn't show an error if two different libraries have overlapping attribute declarations. I suppose it doesn't cause an issue if they both have the same format type. I haven't checked to see what happens if they don't.
As for why Google doesn't prefix attribute names in AppCompat, I figure they want it to be very easy to use, and almost interchangeable with AOSP xml code, so they want the attribute names to match similar attribute names in AOSP. And so they deemed the simplicity of use outweighs the risk. What I suspect they overlook is how disjointed and lacking their documentation is on setting up and using styleables and attributes, so it's not obvious what to watch out for when setting up our own custom views and preferences.
I've seen that all the layout ids are identified by #+id/viewid, but it seems the #+my_group_name/viewid works as well. Is it normal to use this naming convention, or the id must be in the "id" class ? I've checked the forum and found prefix based naming conventions but nothing like this.
In examples: I have a dialog layout called dlgeffect. In this layout:
<CheckedTextView
android:id="#+dlgeffect/text"
android:layout_width="0dip" ... >
I now the id's are reused, but during layout modifications if the ids are unique for the whole project the compiler gives error this way (and not runtime error)
Thanks,
Gzp
EDIT: and of course from java it is referenced as R.dlgeffect.text
I really dont know if you can do this, but always stick to standards, if you want it for reuse porpuse or setting property for more than element at once you can use same id for different element
I built a Python script (with minidom) to manipulate the layout of an Android app, which is defined in an XML file. Widgets are elements in the android namespace, for example:
<TextView android:id="#+id/myId" android:text="..." />
Note the android:id attribute and its required format #+id/.... I didn't find a way to pick that element with getElementById(). Maybe it's because I don't know minidom, but more likely it's because I don't understand XML namespaces deeply.
I remember that id is an attribute to uniquely identify an element in a tree. I never saw a namespaced ID, so my guess is that android:id isn't really an ID, but just an attribute which happens to be called id in the android namespace. In this case there's no way to getElementById, because it works with XML id's. Currently I traverse the dom and check the android:id attribute to get my target element, but this technique is obviously less flexible than getElementById directly
Disclaimer: I tagged this with xslt because I think that xslt people can know the answer since they are used to working with XML and namespaces
OK - I found something else that may be of help to you. Apparently it depends on what has been listed of being of type "ID". Where is that defin ed and can you influence it? I don't know :-( But check How to set element's id in Python's xml.dom.minidom?
See extract below from http://www.w3.org/TR/DOM-Level-2-Core/core.html
getElementById introduced in DOM Level 2
Returns the Element whose ID is given by elementId. If no such element exists, returns null. Behavior is not defined if more than one element has this ID.
Note: The DOM implementation must have information that says which attributes are of type ID. Attributes with the name "ID" are not of type ID unless so defined. Implementations that do not know whether attributes are of type ID or not are expected to return null.
Yes, attributes can have namespaces. The best known example of attribute namespace is the namespace declaration itself:
xmlns:someNamespace="someUri"
The only advantage in using namespaces that I see, is that the same attribute name may be used more than once, when assigned separate namespaces, such as in
<x xmlns:n1="http://www.w3.org"
xmlns:n2="http://www.my.org" >
<good n1:a="1" n2:a="2" />
</x>
Not sure what one would need that for though...
Now for selecting namespaced attributes.
In XSLT/Xpath this is done in normal fashion, including the namespace of course; don't forget the # character. Example for the above XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:n1="http://www.w3.org"
xmlns:n2="http://www.my.org">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="//good">
<root>
<n1><xsl:value-of select="./#n1:a"/></n1>
<n2><xsl:value-of select="./#n2:a"/></n2>
</root>
</xsl:template>
</xsl:stylesheet>
gives
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:n1="http://www.w3.org" xmlns:n2="http://www.my.org">
<n1>1</n1>
<n2>2</n2>
</root>
Android layouts are defined in XML with this namespace declared in the root element:
xmlns:android="http://schemas.android.com/apk/res/android"
Example of an element:
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" />
Why is the android prefix used instead of ommitting it like xmlns="http... ?
Why is the prefix used only in attributes and not in elements?
Interesting question! it sure feel a bit weird.
It was a design choice by Google to be as strict as possible on namespace to handle errors at compile time.
The prefix is not used on elements because theses are representing Java classes: com.android.widget.TextView (com.android.widget.* can always be truncated). The java namespace of this class will be automagically resolved at compile time, so an xml namespace representing a fully qualified java namespace is not welcome here. But attributes can be mapped to any of the inherited java classes of the Element. Hence the namespace on attributes to allow inheritance.
This is done like this mainly because the layout describes Java objects and Google here is using the XML namespace mechanism to help in mapping your Layout with Java objects. So there are collisions between the Java namespace world and XML namespace world.
It also allow us developers to subclass elements, add our own attributes without worrying that the next version of the platform will maybe add an attribute with the same name.
See the two replies to this blog post by Dianne Hackborn, a well-known android engineer working at google: http://www.elharo.com/blog/software-development/xml/2008/09/16/android-xml-weirdness/
Working on my first Android application. I'm wondering if there's a way to use the xmlns in the markup in any way. In Flex, for example, I can define a namespace:
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:cb="com.typeoneerror.apps.app.views.components.*">
<cb:CustomComponent paramName="demo"></cb:CustomComponent>
</mx:VBox>
Android seems to be slightly different. You use the namespace when defining params but not the tag itself. This is a bit wordy to me, so I'm wondering if there's a way to configure or change this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cb="http://schemas.android.com/apk/res/com.typeoneerror.apps.app">
<com.typeoneerror.apps.app.views.components.CustomComponent cb:paramName="demo"/>
</LinearLayout>
I'd like to use
<cb:CustomComponent cb:paramName="demo"></cb:CustomComponent>
Possible?
No, sorry. The element name is a Java class name, and in the case of custom widgets, is a fully-qualified class name.
I have seen some syntax where the element name is View and there is a class attribute with the widget's class name. I can't find that in the docs and don't have an sample available, though.