Android XML Elements and Namespaces - android

Is it not possible to simplify the name of a custom element in an Activity XML file?
<com.library.CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
android:id="#+id/myView"
app:newAttr="value" />
Say for example I have a CustomView control. Do I always have to put "com.library." in front of "CustomView" or is it possible to use xmlns:custom in a FrameLayout so that I don't need to?
This is what I would like to see (if possible):
<CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
android:id="#+id/myView"
app:newAttr="value" />

No. You must specify the fully qualified name of the custom view class. The custom attribites belong to a different namespace. So you nee to have
http://schemas.android.com/apk/res/[your package name].
That is why you have
xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
It is necessary to specify fully qualified name of the custom view and hence
<com.library.CustomView
http://developer.android.com/training/custom-views/create-view.html
The docs does not mention any other solution.
Edit:
There seems to be a workaround as mentioned in the below link. Notice comments on both answers. The authors feels there is a little overhead involved. So its left you to use the below although i recommend you to follow the above method mentioned in the docs.
Using custom Views in XML without using fully-qualified class name

Related

I can't find the documentation for the layout <fragment> element

Okay as everyone somehow seems to think I asked how to create a fragment in xml, let me make this absolutley clear, using the attributes shown in the page that I keep ending up on.
Are there any more attributes that can be used in the <fragment> xml element than these?
<fragment
android:name=""
android:id=""
android:layout_weight=""
android:layout_width=""
android:layout_height=""/>
Looking under Android's R.styleable documentation, I see a bunch of Fragment-related values:
android:fragmentAllowEnterTransitionOverlap
android:fragmentAllowReturnTransitionOverlap
android:fragmentEnterTransition
android:fragmentExitTransition
android:fragmentReenterTransition
android:fragmentReturnTransition
android:fragmentSharedElementEnterTransition
android:fragmentSharedElementReturnTransition
android:id
android:name
android:tag
Search for Fragment_ and you'll see them. Unfortunately, I can't test them myself since I'm not near my IDE, but I think they are what you want.

Can you set a view as a property of another view in an XML layout file?

We have a custom GridView which has headerView and footerView properties. I'm wondering if in Android, it's possible to set those properties from within a layout file.
XAML in Windows lets you do this easily since you can specify properties either via attributes (for things like strings, numbers or other simple types), or via nested elements (for any object type) with a ControlType:PropertyName syntax.
Here's a pseudo-version of what this would look like if Android supported something similar:
<MyCustomGrid
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- This would set the 'headerView' property
on 'MyCustomGrid' to a TextView -->
<MyCustomGrid:headerView>
<TextView android:text="I'm the Header TextView" />
</MyCustomGrid:headerView>
</MyCustomGrid>
Obviously the above is not valid. But is it possible to do something similar in Android, or do I have to do it in the code-behind in the Activity/Fragment?
Yes, you can.
You can create a Custom View by extending the GridView class and add some logic through attributes. This will not work as an attached property from XAML (Like Grid.Column or Grid.Row from XAML UWP) but you can do something like this:
<com.teste.widget.MarqueIVGridView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:my_header="#layout/my_header"
/>
Don't forget to add the namespace at the root of your layout:
xmlns:app="http://schemas.android.com/apk/res-auto"
Google has this sample:
HeaderGridView
It uses a different approach, if you copy this class you will just need to use this "HeaderGridView" and call addHeaderView method from it sending your header view inflated.
Feel free to ask any question and It will be a pleasure to answer.

Namespaces in binding adapter?

I am trying android data-binding and I am really amazed with its capabilities. It really shifts all the getters and setters of views to a single place (layout files or custom binding adapters) .
But, I don't understand what is the use of the namespace here? I was reading a recent article from George on Medium here, and he mentioned that:
Anything in the application namespace doesn’t need any namespace in the parameter, but for attributes in the android namespace, you must give the full attribute name including the “android.”
So, if I don't give a namespace, it works. My custom attributes are namespaced with xmlns:app="http://schemas.android.com/apk/res-auto" . I really don't know what that means.
Say I have a text view where I am doing this like this (hardcoded strings just for example) :
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='#{"Created By:" + user.name + " on " + user.time}' />
It's really good as I can provide arguments here:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:createdBy="#{user.name}"
app:createdAt="#{user.time}" />
And handling that code in Java by setting that text to the same as on above example. This provides an easy to use and understandable code for the layout files.
But, this arguments can collide sometimes. If I am using this at 2 different places with 2 different formats like Created by User A on 7/10/2016 and From User A (7/10/2016). This both can requires same arguments as I showed in second example. How can I distinguish them?
I can also provide third argument like app:format and so that my custom binding function can understand, but can namespaces play the important role here? Can I provide a custom namespaces for multiple data-binding elements and handle them accordingly in my binding adapters? Or namespaces will just be ignored as George mentioned in his article?
In the official documentation they have used bind: namespace and in binding adapter methods they have provided namespace there. I am little bit confused about namespaces' role in data-binding.
XML is very flexible and allows you to provide any number of namespaces. Android, however, isn't (yet) flexible enough to handle more than two -- android and your application's namespace. Android data binding doesn't distinguish between any application namespace name. e.g. bind: or app: doesn't matter because they all refer to http://schemas.android.com/apk/res-auto.
So, the answer to your question is "No." Namespaces won't really help. You could use the android namespace -- assuming there aren't unfortunate collisions. That only extends your flexibility from one to two and I'm pretty sure you want something better than that.
This specific example is perfect for string formatting expressions:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='#{#string/createdBy(user.name, user.time)}' />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='#{#string/fromUser(user.name, user.time)}' />
But generally speaking, you'll have to either use different attributes names for different uses or add an attribute for the differentiator as you suggested.

Is there a way to avoid using the full package name in xml with custom Views (Android)?

I would like to do something like
<TextViewPlus
android:id="#+id/settings_title_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="#string/settings />
instead of
<com.my.really.super.long.package.name.that.wont.autocomplete.TextViewPlus
android:id="#+id/settings_title_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="#string/settings />
I figure I could just put custom Views in the (default) package, but that seems like a bad idea. (EDIT: And upon testing this, it doesn't work anyway) Is there a "good" way to do this?
No, AFAIK you will have to go with the full name.
LayoutInflater.setFactory(LayoutInflater.Factory) allows you to specify an object that performs custom view object creation given the tag name at run time. This could be used to achieve what you want to do. I'd call getFactory() first to retrieve the existing default factory object and use that for any view names that are not your custom views.

Android custom attributes on "normal" views?

After taking a look at theming for Fede's UberMusic I came across the file album_screen.xml. Below is the source of that file. Basically I noticed that his themes have the ability to use custom views that are a part of his application, and that they have this XML namespace at the top theme. I am missing the connection as to how he is able to apply his attributes to views that he does not control, and how Eclipse will compile the cod below without fail. I placed the URL http://schemas.uberdroidstudio.com/theme into my browser's address bar but nothing came up, and I cannot figure out where/ how Eclipse knows the attributes that the namespace supports. Thank you ahead of time for your help.
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:theme="http://schemas.uberdroidstudio.com/theme">
<TextView
android:id="#id/artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.0"
theme:textFilter="uppercase" /> <!-- This is the interesting line -->
I suspect that the theme:textFilter="uppercase" line isn't actually having an effect on the (apparently vanilla) TextView.
As for the URL of the namespace, it is interesting that you can't access it, since it does not appear to be a local styleable (Android would have you refer to a local styleable namespace as http://schemas.android.com/apk/res/your.package). +1 for novelty.
The solution is actually not as complicated as I originally thought. XML namespaces are arbitrary strings that just need to be unique. If your namespace does not start with http://schemas.android.com/apk/res then it is not validated and the APK package is not checked for declare-styleable or the like.
Now a custom namespace if very simple to implement, as illustrated by this code snippet in GitHub. Finally, applying custom XML attributes to "normal" widgets can be accomplished by using the LayoutInflater.Factory and calling setFactory before you inflate your views. Throw it all together and you have a highly theme-able, XML driven application like Fede's UberMusic.

Categories

Resources