An Android project that has no default Activity class has no entry point for any code! This is hardly surprising for a programming paradigm that is event-driven. Without an Activity to receive events, there is nothing to do!
In order to specify an app does do something, we start with the AndroidManifest.xml file. An App that has no Activity has a bare-bone manifest file. There is nothing to say about intents because each intent has to associate with an explicit or implicit Activity subclass.
An Android project that has no default Activity has no Java source file to begin with, either!
It makes sense to start with adding an Activity to an otherwise empty Android project. Right-click on app in the PRoject pane, select ”new—Activity—gallery”, then you can choose among some popular templates to start with.
After you select a particular template activity as the basis, the next screen presents some options.
Reexamining AndroidManifest.xml as follows, we notice some new lines.
The new element added is the <activity> element. This element has a sub-element that specifies when this app is launched from a launcher, the activity corresponding to class MainActivity should be started. The same activity is also designated as the MAIN action of this app.
With at least one activity, an Android app finally has an entry point for coding.
An Activity subclass has many overrideable callbacks. Each callback corresponds to a specific event that can occur to the activity.
“Manual” or programmatic layout has some advantages and some disadvantages. The main disadvantage of manual layout is the sheer tedium of coding the logic to control layout. In addition, there is no easy way to preview how an app may look like without running it.
However, the advantage of manual layout is complete control over the positioning and size of everything using code. This means algorithmic logic can be used to determine attributes at run-time instead of relying static design-time decisions.
Manual layout starts with a ViewGroup object. A ViewGroup object is a container of additional child views.
The onLayout method must be overriden to derive a subclass of ViewGroup. This method should implement the logic to control the layout of child views of a ViewGroup object. The supplied parameters l, t, r and b are in raw actual pixel.
In order for an app to look right on different devices, the actual density of the display must be taken into consideration. With a programmatic layout control, an app can include custom scaling so that an end user may choose to display more items that appear smaller.
To get the density of a display, first use getDisplay of a Vuew to retrieve an object representing the hardware display itself. Then use getMetrics of the Display object to get the actual measurements. Note that a non-null DisplayMetrics object must be passed to getMetrics to store the values.
There are several mechanisms of a View and ViewGroup that are particularly important for programmatic layout control.
The documentation of onMeasure only describes some of the effects of this method. It is suggested that this method be overriden only “to provide better measurements of their (subclasses’) content.”
onMeasure is the callback corresponding to the measure method. In addition to the effects documented, onMeasure sets the actual (as opposed to just measured) width and height of a View object.
Overriding onMeausre is particularly important for a ViewGroup object because otherwise, the child View objects of a ViewGroup object do not get their onMeasure triggered. In other words, even if the width and height of a ViewGroup object is fixed (say the entire display), it is still important to override its onMeasure.
In the simplest case where the ViewGroup object itself has a fixed width and height, start with calling the default method of the super class. This ensures the ViewGroup object itself answers the question as asked by its own container. Then, to trigger the onMeasure methods of child View objects, use the measureChildren method of ViewGroup.
A View object has its boundaries defined by the left, right, top and bottom offsets from the the top left pixel of its parent (container). In the case of programmatic layout control, these values should be set either by the individual setLeft,... methods or collectively using the layout method. These methods should be called within the overriden onLayout method of a ViewGroup object.
One would imagine setting the left and right is the same setting the width, and similarly setting the top and bottom is the same as setting the height. But that is actually not the case!
The L, R, T and B of a view defines its extents as containment. However, the height and width correspond to the “logical” dimensions. This means a View object may have a height that is greater than b-t. This allows the use of a scroll bar to scroll within a View object.
Manually laying out a Button object is more work than imagined. To be specific, it takes some extra work to make a button look right. This is due to the background Drawable of a button defaults to a shape that clears the border of a button (to allow the specification of a shadow).