Android Programming In Kotlin: Layouts and Autonaming Components
Written by Mike James   
Wednesday, 27 December 2017
Article Index
Android Programming In Kotlin: Layouts and Autonaming Components
Finding View Objects

Programming Android using Kotlin has a lot of things to make life easy, but one of the best hidden features isn't even part of the language. The Kotlin plugin will add properties that give you direct access to the components in a layout. No more findViewById!

 

Android Programming In Kotlin
Starting with an App

Covers Android Studio 3 and Constraint Layout.

Is now available as a print book:

coverKotlinsmall

Buy from: Amazon

Contents

  1. Getting Started With Android Studio 3
  2. The Activity And The UI
        Extract: Activity & UI  
  3. Building The UI and a Calculator App
        Extract: A First App
  4. Android Events
  5. Basic Controls
        Extract Basic Controls
        Extract More Controls ***NEW!
  6. Layout Containers
        Extract Layouts - LinearLayout
  7. The ConstraintLayout 
        Extract Bias & Chains
  8. Programming The UI
        Extract Programming the UI
        Extract Layouts and Autonaming Components
  9. Menus & The Action Bar
  10. Menus, Context & Popup
  11. Resources
        Extract Conditional Resources
  12. Beginning Bitmap Graphics
        Extract Animation
  13. Staying Alive! Lifecycle & State
        Extract  State Managment
  14. Spinners
  15. Pickers
  16. ListView And Adapters
  17. Android The Kotlin Way

If you are interested in creating custom template also see:

Custom Projects In Android Studio

Androidgears

 

The ViewGroup

An Activity can only show a single View object so how can we ever create a complex UI with multiple buttons, textViews and other components?

The answer, and you probably already guessed it, is that there are Layout, or ViewGroup, objects which can be used to host other View objects.

You already know about using Layouts in the Layout Editor or in an XML file, but they, like all UI elements, correspond to particular classes that do the actual work.

A ViewGroup can display multiple View objects. So in nearly all cases the View object that is associated with an Activity is a Layout View. When the Activity asks the Layout View to render itself, by calling its onDraw method, the Layout calls the onDraw method of each of the View objects it contains and puts them together to make a single result. Of course, it also performs a layout operation positioning and sizing the View objects it contains. 

So a Layout does two things: 

  • it hosts other View objects

  • it performs the layout function after which it is named. 

The View Hierarchy

Notice also that a Layout can contain other Layouts and so the set of View objects that make up a UI is structured like a tree, the View hierarchy. When the screen is redrawn each View object is asked to draw itself and this is done for all View objects in the hierarchy from top to bottom. 

Normally the View hierarchy is drawn just once when the Activity loads. If an area of the screen is obscured by another graphic for any reason, the redraw is clever enough not to draw the entire View hierarchy. It only redraws View objects that intersect with the invalidated area of the screen. The View hierarchy is also involved in passing events between objects and in determining which component has the current focus.

XML Layout

So far the principles of the graphic system are simple enough. Every control or component corresponds to a View object and you can build a UI by creating View objects in code and adding them to Layouts. You control the way the View objects are arranged using the LayoutParams object or by directly setting properties. An Activity will draw its View hierarchy to the screen when it needs to. OK, this is how to create a UI in code, but so far we have been building a UI using the Layout Editor.

How does this relate to the View hierarchy?

The Layout Editor creates an XML file which describes the View hierarchy that you want to create. The way that this works is fairly obvious. Each tag in the XML file corresponds to a View object for which you want to create an instance. For example:

<LinearLayout>
</LinearLayout>

creates an instance of a LinearLayout object.

Nesting tags within a layout indicates that the objects created need to be added to the layout as child Views. For example:

<LinearLayout>
 <Button />
</LinearLayout>

creates a LinearLayout object and a Button object and then adds the Button object to the LinearLayout using its addView method. You can see that the XML captures the idea of the View hierarchy perfectly. 

To set object properties all you have to do is is use the corresponding attributes in the XML. For example to set the button's text:

<Button
  android:text="New Button"
/>

Layout parameters are set using properties prefixed with layout_property. For example:

<Button
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
/>

That is really all there is to it. The XML defines a hierarchy of objects and their properties and the system reads the file and creates the objects. This use of XML as an object instantiation system is not an uncommon one. Of course, the XML created by the Layout Editor looks a lot more complicated than the examples above, but this is mainly because of the number of attributes it defines. The basic idea is still the same. 

Inflation Theory

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. Instead you can simply use an existing one supplied by the system using the LayoutInflater property of the Activity. 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 can use:

val inf = layoutInflater val myView = 
           inf.inflate(R.layout.activity_main,null) setContentView(myView)

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:

setContentView(R.layout.activity_main)

which calls the LayoutInflater and sets the view in a single 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, which do 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:

inflate(R.layout.activity_main,root, true/false)

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. 

 

coverKotlinsmall

 



Last Updated ( Wednesday, 27 December 2017 )