Login     Sign Up
Cyril Sermon (@admin)
10 months ago
58 Views

Introducing Layouts

Layout Managers (more generally, “layouts”) are extensions of the ViewGroup class designed to control the position of child controls on a screen. Layouts can be nested, letting you create arbitrarily complex interfaces using a combination of Layout Managers.

The Android SDK includes some simple layouts to help you construct your UI. It’s up to you to select the right combination of layouts to make your interface easy to understand and use.

The following list includes some of the more versatile layout classes available:

❑FrameLayout The simplest of the Layout Managers, the Frame Layout simply pins each child view to the top left corner. Adding multiple children stacks each new child on top of the previ-ous, with each new View obscuring the last.

❑LinearLayout A Linear Layout adds each child View in a straight line, either vertically or hori-zontally. A vertical layout has one child View per row, while a horizontal layout has a single row of Views. The Linear Layout Manager allows you to specify a “weight” for each child View that controls the relative size of each within the available space.

❑RelativeLayout Using the Relative Layout, you can define the positions of each of the child Views relative to each other and the screen boundaries.

❑TableLayout The Table Layout lets you lay out Views using a grid of rows and columns. Tables can span multiple rows and columns, and columns can be set to shrink or grow.

❑AbsoluteLayout In an Absolute Layout, each child View’s position is defined in absolute coor-dinates. Using this class, you can guarantee the exact layout of your components, but at a price. Compared to the previous managers, describing a layout in absolute terms means that your lay-out can’t dynamically adjust for different screen resolutions and orientations.

The Android documentation describes the features and properties of each layout class in detail, so rather than repeating it here, I’ll refer you to http://code.google.com/android/devel/ui/layout.html.

Later in this chapter, you’ll also learn how to create compound controls (widgets made up of several interconnected Views) by extending these layout classes.

Using Layouts

The preferred way to implement layouts is in XML using external resources. A layout XML must con-tain a single root element. This root node can contain as many nested layouts and Views as necessary to construct an arbitrarily complex screen.

The following XML snippet shows a simple layout that places a TextView above an EditText control using a LinearLayout configured to lay out vertically:

<?xml version=”1.0” encoding=”utf-8”?>

<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”

android:orientation=”vertical”

android:layout_width=”fill_parent”

android:layout_height=”fill_parent”>

<TextView

android:layout_width=”fill_parent”

android:layout_height=”wrap_content”

android:text=”Enter Text Below”

/>

<EditText

android:layout_width=”fill_parent”

android:layout_height=”wrap_content”

android:text=”Text Goes Here!”

/>

</LinearLayout>

Implementing layouts in XML decouples the presentation layer from View and Activity code. It also lets you create hardware-specific variations that are dynamically loaded without requiring code changes.

When it’s preferred, or required, you can implement layouts in code. When assigning Views to layouts, it’s important to apply LayoutParameters using the setLayoutParams method, or passing them in to the addView call as shown below:

LinearLayout ll = new LinearLayout(this);

ll.setOrientation(LinearLayout.VERTICAL);

TextView myTextView = new TextView(this);

EditText myEditText = new EditText(this);

myTextView.setText(“Enter Text Below”);

myEditText.setText(“Text Goes Here!”);

int lHeight = LinearLayout.LayoutParams.FILL_PARENT; int lWidth = LinearLayout.LayoutParams.WRAP_CONTENT;

ll.addView(myTextView, new LinearLayout.LayoutParams(lHeight, lWidth)); ll.addView(myEditText, new LinearLayout.LayoutParams(lHeight, lWidth)); setContentView(ll);

Creating New Views

The ability to extend existing Views, create composite widgets, and create unique new controls lets you create beautiful User Interfaces optimized for your particular workflow. Android lets you subclass the existing widget toolbox and implement your own View controls, giving you total freedom to tailor your User Interface to maximize the user experience.

When you design a User Interface, it’s important to balance raw aesthetics and usability. With the power to create your own custom controls comes the temptation to rebuild all of them from scratch. Resist that urge. The standard widgets will be familiar to users from other Android applications. On small screens with users often paying limited attention, familiarity can often provide better usability than a slightly shinier widget.

Deciding on your approach when creating a new View depends on what you want to achieve:

❑Modify or extend the appearance and/or behavior of an existing control when it already supplies the basic functionality you want. By overriding the event handlers and onDraw, but still calling back to the superclass’s methods, you can customize the control without having to reimplement its functionality. For example, you could customize a TextView to display a set number of deci-mal points.

❑Combine controls to create atomic, reusable widgets that leverage the functionality of several interconnected controls. For example, you could create a dropdown combo box by combining a TextView and a Button that displays a floating ListView when clicked.

❑Create an entirely new control when you need a completely different interface that can’t be achieved by changing or combining existing controls.

Modifying Existing Views

The toolbox includes a lot of common UI requirements, but the controls are necessarily generic. By cus-tomizing these basic Views, you avoid reimplementing existing behavior while still tailoring the User Interface, and functionality, of each control to your application’s needs.

To create a new widget based on an existing control, create a new class that extends it — as shown in the following skeleton code that extends TextView:

import android.content.Context;

import android.util.AttributeSet;

import android.widget.TextView;

public class MyTextView extends TextView {

public MyTextView (Context context, AttributeSet attrs, int defStyle)

{

super(context, attrs, defStyle);

}

public MyTextView (Context context) {

super(context);

}

public MyTextView (Context context, AttributeSet attrs) { super(context, attrs);

}

}

To override the appearance or behavior of your new View, override and extend the event handlers asso-ciated with the behavior you want to change.

In the following skeleton code, the onDraw method is overridden to modify the View’s appearance, and the onKeyDown handler is overridden to allow custom key press handling:

public class MyTextView extends TextView {

public MyTextView (Context context, AttributeSet ats, int defStyle) { super(context, ats, defStyle);

}

public MyTextView (Context context) {

super(context);

}

public MyTextView (Context context, AttributeSet attrs) { super(context, attrs);

}

@Override

public void onDraw(Canvas canvas) {

[ ... Draw things on the canvas under the text ... ]

Render the text as usual using the TextView base class. super.onDraw(canvas);

[ ... Draw things on the canvas over the text ... ]

}

@Override

public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {

... Perform some special processing ... ]

... based on a particular key press ... ]

Use the existing functionality implemented by

the base class to respond to a key press event. return super.onKeyDown(keyCode, keyEvent);

}

}

The User Interface event handlers available within Views are covered in more detail later in this chapter.