|Android Adventures - UI Graphics A Deep Dive
|Written by Mike James
|Tuesday, 07 April 2015
Page 3 of 4
The final big question to be answered is how does the XML get converted into a real object hierarchy?
The answer to this is to use an "inflater".
To inflate a layout is Android jargon for instantiating the objects defined by an XML file.
You normally don't have to call an inflater because the system does it for you behind the scenes, but you can if you want to.
For example, to inflate a layout you would use an instance of the LayoutInflater.
Normally you wouldn't create a fresh instance, but opt to borrow the system's using getLayoutInflater. Once you have the LayoutInflater you can use one of its many inflate methods to create a View object hierarchy as specified by the XML. Which method you use depends on where the XML is stored. You can simply supply a resource id for an XML file included in the res directory.
For example to inflate the usual activity_main.xml layout you would use:
The second parameter of inflate can be used to provide a View object to act as the root container for the inflated View hierarchy. The container is just used as a reference "parent" for the purposes of calculating the layout. That is it simply provides the container that everything has to fit into according to the layout rules.
Of course this is entirely equivalent to the usual:
which calls the LayoutInflater and sets the view in one instruction.
The only reason that you would manually inflate an XML layout is if you wanted to do something clever such as put one layout together with another or in some way manipulate the View hierarchy.
Notice that there are other types of inflater objects - e.g. the Menu inflater but it does the same job of converting XML to instantiated objects with the given properties. We will come back to these more specialized inflaters when we look at menus in the next chapter.
There is also a version of the inflate method:
which will inflate the XML resource using root as its container for the purposes of layout if the last parameter is false and it will add the inflated View to the root if the last parameter is true.
Finding View objects
One problem we have to solve if you want to work with the View hierarchy created by an inflater is finding View objects in the hierarchy.
In the example where we built the View hierarchy in code it was easy to keep track of a button or a textView by simply keeping a reference to when it was created.
An inflater simply returns the View hierarchy without an easy way to get at a particular object, a button say.
One way of solving the problem would be to "walk" the View tree. A ViewGroup object e.g. a layout not only has an addView method but a range of methods that allow you to access objects it contains. Each child object is assigned an integer index - think of it like an array. The method:
will return the child object at index i.
You can also use:
to find out how many child objects are stored in the container.
Using these methods you can search the hierarchy for the View object you want but how do you know which one it is?
The answer to this one is that all View objects have an id property which should identify them uniquely. There are getid and setid methods but usually the id property is set as part of the XML file.
To avoid you having to work out an id value the standard way of setting an id is to define a resource within the XML file:
When the XML file is inflated the @+ symbol is interpreted as "create a resource". An integer id is generated using the generateViewId method and this is used to both create the id property and to add a my_button property to the R.id object.
The only minor complication is that when you set an id using the designer it will auto generate the @+id/ for you. So in the Properties window you will see my_button not @+id/my_button. This is helpful but it can be confusing.
There is a lot more to say about resources, but for the moment this is enough to understand what is going on. Resources deserve a chapter all to themselves.
What all this means is that not only do you get an autogenerated id value, but also a way to get this value into running code. You could use the getChildAt methods to step through all of the View objects in the hierarchy, but it is much easier to use:
which returns the object in one instruction.
In general the general method is to inflate the XML, set it as the content of the view and then use the findViewById to locate any View object you want to work with in code.
It is worth mentioning that a new way of working with View objects - data binding - is making its way into Android Studio. It will in the future make findViewById redundant and make the UI easier to work with. However it is important to know the basics of Android UI construction and for the moment it is better to use the tried and trusted methods.
|Last Updated ( Friday, 28 October 2016 )