Page 1 of 2
If you want to be a really good Android programmer, not only do you need to know how to create a UI, but also how the UI is created. To be really confident in what you are doing, you need to understand some of the inner workings of the Android graphics system.
Android Adventures With Android Studio
- Getting Started With Android Studio
- The Activity And The UI
- Building The UI and a Calculator App
- Lifecycle and State
- Basic Controls And Events
- UI Graphics A Deep Dive
- Introducing Fragments
- Fragments and XML
- Activity And Fragment Communication
- Managing Fragments
- Dialog Fragments
In the latest version Android Studio changed its Project templates so that all projects, including Blank Activity, make use of a fragment for the UI. This is not a bad idea in that fragments make the UI more flexible, but they make learning a bit more complicated than it needs to be. Rest assured that Android Adventures will cover fragments - but in a later part of the series.
In the meantime we have provided a custom template that doesn't use a fragment and this effectively restores a simple blank activity project type that will work with the examples discussed not only in this article but in several more.
All you need to do is to download SimpleBlankActivity.zip from the CodeBin (note you have to register first). Once you have the new template simply unzip it to the
directory. You have to restart Android Studio for this to take effect.
With this template installed you can now follow the rest of the instructions in Android Adventures.
If you want to know more about how the template works see:Custom Projects In Android Studio.
A UI Library
There are lots of different UI construction kits for Java and other languages - AWT, Swing, Qt, MFC, WPF and on - and you might think that mastering them all would be a difficult if not impossible task. In fact it is a lot easier than you might think because most UI libraries use the same general approach and the Android UI library which doesn't seem to have a name is no different.
Let's take a careful look at how it works.
An Activity has a window associated with it and this is usually the entire graphics screen of the device it is running on. In other words, an Activity can allow other Java classes to draw on the devices screen. However, rather than simply providing direct access to the graphics hardware there is an extensive set of classes that make building a UI and performing graphics operations easier.
Before we look at general graphics we need to first find out how the UI is constructed.
The basis of all UI components and general 2D graphics is the View class.
This is a general purpose class that has lots and lots of methods and properties that determine how it will display the widget or other graphics entity it represents. It also takes part in the event handling system which means Views can respond to events.
There are View classes that implement all of the standard widgets that you make use of in the Android Studio designer, i.e. button, textview and so on.
Every View object has an onDraw method that can draw the graphic representation of what it represents onto a Canvas object which is essentially a bitmap with drawing methods.
What happens is that the Activity calls the View's onDraw method when it needs to update the UI and passes it a Canvas object that it then renders to the screen - you don't have to worry about how the Canvas is rendered to the screen at this level. You can think of this as "every View object know how to draw itself".
- An Activity can be associated with a View object.
- When the Activity needs to draw its UI it calls the View objects's onDraw method e.g. view.onDraw(Canvas)
- The View object then draws on the Canvas whatever it needs to - a button, text or whatever.
- The Activity then displays the Canvas object on the screen.
An Activity can be associated with a single View object which determines what is drawn on the screen. This might seem a bit limited but, as you will see, it is far from limited.
How do you set a View object to show in the Activities window?
The answer is that you use the Activities setContentView method - which is what we have been doing all along.
To see this in action, start a new Simple Blank Activity project and add the following code to the onCreate :
Button b = new Button(this);
The first instruction creates a Button object, which is a subclass of View, and the second sets this as the Activities View.
If you run this program what you will see is a grey area that fills the entire screen. Yes, this is the button! You can even click it although, with no event handler, nothing happens.
To make the button a tiny bit more interesting we can customize it by setting properties.
Button b = new Button(this);
If you run this you will see a button that fills the screen with the caption "Hello Button".
Don't bother setting any layout properties because at the moment there is no layout in force so they will be ignored. How to get a layout in action is our next topic.
Layout - ViewGroup
If an Activity can only show a single View object how can we ever create a complex UI with multiple buttons, textViews and other widgets?
The answer is, and you probably already guessed it, is that there are Layout or ViewGroup objects which can be used to host other 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.
To see this in action try:
LinearLayout linLayout=new LinearLayout(this);
Button b = new Button(this);
The first instruction creates a LinearLayout object. This is a subclass of View that can contain other View objects and it organizes them in a left to right or top to bottom way depending on the setting of its orientation property. Next we create a button object and then use the standard addView method of the LinearLayout to add it to the layout.
If you run this program you will see a button right at the top left of the screen. You can add more buttons to see how the default linear layout works:
At the moment we are relying on default settings for the View objects we are creating. However, in practice you could spend the time and lines of code to set all of the properties needed to create any user interface and layout you wanted to.
You now know how to create a UI completely in code. All you have to do is create all of the widget objects you need, set their properties and add them to suitable layout objects.
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 then the redraw it clever enough not to draw the entire View hierarchy. It only redraws View objects that intersect with the invalidated area of the screen. There is more to say on this later.
The View hierarchy is also involved in passing events between objects and in determining which widget has the current focus.