Download Android8Layouts

Document related concepts
no text concepts found
Transcript
Android 8: Layouts and Input
Controls
Kirk Scott
1
2
• These are the sections in this unit:
• 8.1 Introduction
• 8.2 Layouts (Taken from Resources Section of
Tutorials)
• 8.3 Layouts (Taken from Layouts Section of
Tutorials)
• 8.4 Linear Layout
• 8.5 Relative Layout
• 8.6 List View
• 8.7 Grid View
3
8.1 Introduction
4
• As usual, the decision to present this material at
this point is based partially on background ideas
found in the book
• The contents of the overheads consist largely of
material taken from the online tutorials, with
occasional commentary by me
• The commentary will either be introduced as
commentary or appear in square brackets
• If not set off in this way, the content is taken from
the tutorials
5
• As mentioned before, what you’re getting is
an idiosyncratic path through some of the
various topics covered in the tutorials
• The goal is to cover enough of the items
involved in sufficient depth so that the
perceptive learner could pick up more when
needed
6
8.2 Layouts (Taken from Resources
Section of Tutorials)
7
• Layout Resource
• A layout resource defines the architecture for the UI in
an Activity or a component of a UI.
• file location:
• res/layout/filename.xml
• The filename will be used as the resource ID.
• compiled resource datatype:
• Resource pointer to a View (or subclass) resource.
• resource reference:
• In Java: R.layout.filename
• In XML: @[package:]layout/filename
8
•
•
syntax:
<?xml version="1.0" encoding="utf-8"?>
<ViewGroup
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@[+][package:]id/resource_name"
android:layout_height=["dimension" | "fill_parent" |
"wrap_content"]
android:layout_width=["dimension" | "fill_parent" |
"wrap_content"]
[ViewGroup-specific attributes] >
<View
android:id="@[+][package:]id/resource_name"
android:layout_height=["dimension" | "fill_parent" |
"wrap_content"]
android:layout_width=["dimension" | "fill_parent" |
"wrap_content"]
[View-specific attributes] >
<requestFocus/>
</View>
<ViewGroup >
<View />
</ViewGroup>
<include layout="@layout/layout_resource"/>
</ViewGroup>
9
• Note:
• The root element can be either a ViewGroup,
a View, or a <merge> element, but there must
be only one root element and it must contain
the xmlns:android attribute with the android
namespace as shown.
10
•
•
•
•
elements:
<ViewGroup>
A container for other View elements.
There are many different kinds of ViewGroup
objects and each one lets you specify the layout
of the child elements in different ways.
• Different kinds of ViewGroup objects include
LinearLayout, RelativeLayout, and FrameLayout.
• You should not assume that any derivation of
ViewGroup will accept nested Views.
11
• Some ViewGroups are implementations of the
AdapterView class, which determines its
children only from an Adapter.
• [This is not the same as an adapter class in the
Java API.
• It has more in common with the adapter
design pattern of CSCE 202.
• More information will be given later in this
unit.]
12
•
•
•
•
attributes:
android:id
Resource ID.
A unique resource name for the element,
which you can use to obtain a reference to the
ViewGroup from your application.
• See more about the value for android:id
below.
13
• android:layout_height
• Dimension or keyword. Required.
• The height for the group, as a dimension value
(or dimension resource) or a keyword
("fill_parent" or "wrap_content").
• See the valid values below.
14
• android:layout_width
• Dimension or keyword. Required.
• The width for the group, as a dimension value
(or dimension resource) or a keyword
("fill_parent" or "wrap_content").
• See the valid values below.
15
• More attributes are supported by the
ViewGroup base class, and many more are
supported by each implementation of
ViewGroup.
• For a reference of all available attributes, see
the corresponding reference documentation
for the ViewGroup class (for example, the
LinearLayout XML attributes).
16
• <View>
• An individual UI component, generally referred to as a
"widget".
• Different kinds of View objects include TextView, Button,
and CheckBox.
• attributes:
• android:id
• Resource ID.
• A unique resource name for the element, which you can
use to obtain a reference to the View from your application.
• See more about the value for android:id below.
17
• android:layout_height
• Dimension or keyword. Required.
• The height for the element, as a dimension
value (or dimension resource) or a keyword
("fill_parent" or "wrap_content").
• See the valid values below.
18
• android:layout_width
• Dimension or keyword. Required.
• The width for the element, as a dimension
value (or dimension resource) or a keyword
("fill_parent" or "wrap_content").
• See the valid values below.
19
• More attributes are supported by the View
base class, and many more are supported by
each implementation of View.
• Read Layouts for more information.
• For a reference of all available attributes, see
the corresponding reference documentation
(for example, the TextView XML attributes).
20
• <requestFocus>
• Any element representing a View object can
include this empty element, which gives its
parent initial focus on the screen.
• You can have only one of these elements per
file.
21
•
•
•
•
•
•
<include>
Includes a layout file into this layout.
attributes:
layout
Layout resource. Required.
Reference to a layout resource.
22
• android:id
• Resource ID.
• Overrides the ID given to the root view in the
included layout.
• android:layout_height
• Dimension or keyword.
• Overrides the height given to the root view in the
included layout.
• Only effective if android:layout_width is also
declared.
23
• android:layout_width
• Dimension or keyword.
• Overrides the width given to the root view in the
included layout.
• Only effective if android:layout_height is also
declared.
• You can include any other layout attributes in the
<include> that are supported by the root element
in the included layout and they will override
those defined in the root element.
24
• Caution:
• If you want to override layout attributes using
the <include> tag, you must override both
android:layout_height and
android:layout_width in order for other layout
attributes to take effect.
25
• Another way to include a layout is to use
ViewStub.
• It is a lightweight View that consumes no
layout space until you explicitly inflate it, at
which point, it includes a layout file defined by
its android:layout attribute.
• For more information about using ViewStub,
read Loading Views On Demand.
26
• <merge>
• An alternative root element that is not drawn in the
layout hierarchy.
• Using this as the root element is useful when you know
that this layout will be placed into a layout that already
contains the appropriate parent View to contain the
children of the <merge> element.
• This is particularly useful when you plan to include this
layout in another layout file using <include> and this
layout doesn't require a different ViewGroup container.
• For more information about merging layouts, read Reusing Layouts with <include/>.
27
• Value for android:id
• For the ID value, you should usually use this
syntax form: "@+id/name".
• The plus symbol, +, indicates that this is a new
resource ID and the aapt tool will create a new
resource integer in the R.java class, if it
doesn't already exist. For example:
• <TextView android:id="@+id/nameTextbox"/>
28
• The nameTextbox name is now a resource ID
attached to this element.
• You can then refer to the TextView to which the
ID is associated in Java:
• findViewById(R.id.nameTextbox);
• This code returns the TextView object.
• However, if you have already defined an ID
resource (and it is not already used), then you
can apply that ID to a View element by excluding
the plus symbol in the android:id value.
29
• Value for android:layout_height and
android:layout_width:
• The height and width value can be expressed
using any of the dimension units supported by
Android (px, dp, sp, pt, in, mm) or with the
following keywords:
30
Value
Description
match_parent
Sets the dimension to match that of the
parent element. Added in API Level 8 to
deprecate fill_parent.
fill_parent
Sets the dimension to match that of the
parent element.
wrap_content
Sets the dimension only to the size
required to fit the content of this
element.
31
• Custom View elements
• You can create your own custom View and
ViewGroup elements and apply them to your
layout the same as a standard layout element.
• You can also specify the attributes supported
in the XML element.
• To learn more, see the Custom Components
developer guide.
32
•
•
example:
XML file saved at res/layout/main_activity.xml: <?xml
version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/androi
d"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
</LinearLayout>
33
• This application code will load the layout for an
Activity, in the onCreate() method:
•
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
• [Read it again for the second time…
• The point is that the onCreate() method starts with a
setContentView() call.
• This is what connects a Java app file to its layout file.]
34
8.3 Layouts (Taken from Layouts
Section of Tutorials)
35
• Layouts
• A layout defines the visual structure for a user
interface, such as the UI for an activity or app
widget.
• You can declare a layout in two ways:
• [1] Declare UI elements in XML.
• Android provides a straightforward XML
vocabulary that corresponds to the View classes
and subclasses, such as those for widgets and
layouts.
36
• [2] Instantiate layout elements at runtime.
• Your application can create View and
ViewGroup objects (and manipulate their
properties) programmatically.
37
• The Android framework gives you the flexibility to
use either or both of these methods for declaring
and managing your application's UI.
• For example, you could declare your application's
default layouts in XML, including the screen
elements that will appear in them and their
properties.
• You could then add code in your application that
would modify the state of the screen objects,
including those declared in XML, at run time.
38
• The advantage to declaring your UI in XML is
that it enables you to better separate the
presentation of your application from the
code that controls its behavior.
• Your UI descriptions are external to your
application code, which means that you can
modify or adapt it without having to modify
your source code and recompile.
39
• For example, you can create XML layouts for
different screen orientations, different device
screen sizes, and different languages.
• Additionally, declaring the layout in XML
makes it easier to visualize the structure of
your UI, so it's easier to debug problems.
• As such, this document focuses on teaching
you how to declare your layout in XML.
40
• If you're interested in instantiating View
objects at runtime, refer to the ViewGroup
and View class references.
41
• In general, the XML vocabulary for declaring
UI elements closely follows the structure and
naming of the classes and methods, where
element names correspond to class names
and attribute names correspond to methods.
• In fact, the correspondence is often so direct
that you can guess what XML attribute
corresponds to a class method, or guess what
class corresponds to a given xml element.
42
• However, note that not all vocabulary is
identical.
• In some cases, there are slight naming
differences.
43
• For example, the EditText element has a text
attribute that corresponds to
EditText.setText().
• [They got their explanations slightly out of
order.
• The text attribute and setText() method are an
example of correspondence.
• The are not intended as an example of a case
with a slight difference.]
44
• Tip:
• Learn more about different layout types in
Common Layout Objects.
• There are also a collection of tutorials on
building various layouts in the Hello Views
tutorial guide.
45
• Write the XML
• Using Android's XML vocabulary, you can
quickly design UI layouts and the screen
elements they contain, in the same way you
create web pages in HTML — with a series of
nested elements.
• Each layout file must contain exactly one root
element, which must be a View or ViewGroup
object.
46
• Once you've defined the root element, you
can add additional layout objects or widgets
as child elements to gradually build a View
hierarchy that defines your layout.
• For example, here's an XML layout that uses a
vertical LinearLayout to hold a TextView and a
Button:
47
•
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/androi
d"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
</LinearLayout>
48
• After you've declared your layout in XML, save
the file with the .xml extension, in your
Android project's res/layout/ directory, so it
will properly compile.
• More information about the syntax for a
layout XML file is available in the Layout
Resources document.
49
• Load the XML Resource
• When you compile your application, each XML
layout file is compiled into a View resource.
• You should load the layout resource from your
application code, in your Activity.onCreate()
callback implementation.
50
• Do so by calling setContentView(), passing it
the reference to your layout resource in the
form of:
• R.layout.layout_file_name
• For example, if your XML layout is saved as
main_layout.xml, you would load it for your
Activity like so:
51
• public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
}
• The onCreate() callback method in your
Activity is called by the Android framework
when your Activity is launched (see the
discussion about lifecycles, in the Activities
document).
52
• [It may be worth noting something here:
• You can access layouts directly using their name
as given in R.java:
• setContentView(R.layout.main_layout);
• Contrast this with how you acquire a reference to
an individual view in a layout:
• EditText myEditText = (EditText)
findViewById(R.id.input_message_view);
53
• Or how you access a resource:
•
•
•
Resources res = getResources();
String[] prompts = res.getStringArray(R.array.prompt_array);
int colorIndex = res.getInteger(R.integer.numberInColorCycle);
• ]
54
• Attributes
• Every View and ViewGroup object supports
their own variety of XML attributes.
• Some attributes are specific to a View object
(for example, TextView supports the textSize
attribute), but these attributes are also
inherited by any View objects that may extend
this class.
55
• Some are common to all View objects,
because they are inherited from the root View
class (like the id attribute).
• And, other attributes are considered "layout
parameters," which are attributes that
describe certain layout orientations of the
View object, as defined by that object's parent
ViewGroup object.
56
• ID
• Any View object may have an integer ID
associated with it, to uniquely identify the
View within the tree.
• When the application is compiled, this ID is
referenced as an integer, but the ID is typically
assigned in the layout XML file as a string, in
the id attribute.
57
• This is an XML attribute common to all View
objects (defined by the View class) and you
will use it very often.
• The syntax for an ID, inside an XML tag is:
• android:id="@+id/my_button"
58
• The at-symbol (@) at the beginning of the
string indicates that the XML parser should
parse and expand the rest of the ID string and
identify it as an ID resource.
• The plus-symbol (+) means that this is a new
resource name that must be created and
added to our resources (in the R.java file).
59
• There are a number of other ID resources that
are offered by the Android framework.
• When referencing an Android resource ID, you
do not need the plus-symbol, but must add
the android package namespace, like so:
• android:id="@android:id/empty"
60
• With the android package namespace in place,
we're now referencing an ID from the android.R
resources class, rather than the local resources
class.
• [If accurate, this is an interesting statement.
• We’re being told something about the meaning
of the syntax.
• Java app code depends on R.java.
• After the related project files are built, layout and
other resource files also depend on R.java for
id’s.]
61
• In order to create views and reference them
from the application, a common pattern is to:
• 1. Define a view/widget in the layout file and
assign it a unique ID:
• <Button android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/my_button_text"/>
62
• 2. Then create an instance of the view object and
capture it from the layout (typically in the
onCreate() method):
• Button myButton = (Button)
findViewById(R.id.my_button);
• [You’re not creating an instance of the object.
• You’re recovering a reference to the object as
defined/created in the layout file.]
63
• Defining IDs for view objects is important
when creating a RelativeLayout.
• In a relative layout, sibling views can define
their layout relative to another sibling view,
which is referenced by the unique ID.
64
• An ID need not be unique throughout the
entire tree, but it should be unique within the
part of the tree you are searching (which may
often be the entire tree, so it's best to be
completely unique when possible).
• [Clowns: Just make them globally unique.]
65
• Layout Parameters
• XML layout attributes named layout_something
define layout parameters for the View that are
appropriate for the ViewGroup in which it
resides.
• Every ViewGroup class implements a nested class
that extends ViewGroup.LayoutParams.
• This subclass contains property types that define
the size and position for each child view, as
appropriate for the view group.
66
• As you can see in figure 1, the parent view group
defines layout parameters for each child view
(including the child view group).
• [Following overhead]
• [General note on this topic:
• What they seem to be saying is that a parent in
effect defines what kinds of parameters its
children will have.
• It’s up to the children to use values which are
appropriate to the parameters defined in their
parents.]
67
Figure 1. Visualization of a view hierarchy with
layout parameters associated with each view.
68
• Note that every LayoutParams subclass has its
own syntax for setting values.
• Each child element must define LayoutParams
that are appropriate for its parent, though it may
also define different LayoutParams for its own
children.
• All view groups include a width and height
(layout_width and layout_height), and each view
is required to define them.
• Many LayoutParams also include optional
margins and borders.
69
• You can specify width and height with exact
measurements, though you probably won't want
to do this often.
• More often, you will use one of these constants
to set the width or height:
• wrap_content tells your view to size itself to the
dimensions required by its content
• fill_parent (renamed match_parent in API Level 8)
tells your view to become as big as its parent
view group will allow.
70
• In general, specifying a layout width and height
using absolute units such as pixels is not
recommended.
• Instead, using relative measurements such as
density-independent pixel units (dp),
wrap_content, or fill_parent, is a better
approach, because it helps ensure that your
application will display properly across a variety
of device screen sizes.
• The accepted measurement types are defined in
the Available Resources document.
71
• Layout Position
• The geometry of a view is that of a rectangle.
• A view has a location, expressed as a pair of
left and top coordinates, and two dimensions,
expressed as a width and a height.
• The unit for location and dimensions is the
pixel.
72
• It is possible to retrieve the location of a view
by invoking the methods getLeft() and
getTop().
• The former returns the left, or X, coordinate of
the rectangle representing the view.
• The latter returns the top, or Y, coordinate of
the rectangle representing the view.
• [Notice the similarity with the bounding box in
Java graphics.]
73
• These methods both return the location of the
view relative to its parent.
• For instance, when getLeft() returns 20, that
means the view is located 20 pixels to the
right of the left edge of its direct parent.
• [Keep in mind that this is of pretty remote
usefulness.
• In general we’d like to avoid hardcoding
dimensional values.]
74
• In addition, several convenience methods are
offered to avoid unnecessary computations,
namely getRight() and getBottom().
• These methods return the coordinates of the
right and bottom edges of the rectangle
representing the view.
• For instance, calling getRight() is similar to the
following computation: getLeft() + getWidth().
75
• Size, Padding and Margins
• The size of a view is expressed with a width and a
height.
• A view actually possess two pairs of width and height
values.
• The first pair is known as measured width and
measured height.
• These dimensions define how big a view wants to be
within its parent.
• The measured dimensions can be obtained by calling
getMeasuredWidth() and getMeasuredHeight().
76
• The second pair is simply known as width and
height, or sometimes drawing width and drawing
height.
• These dimensions define the actual size of the
view on screen, at drawing time and after layout.
• These values may, but do not have to, be
different from the measured width and height.
• The width and height can be obtained by calling
getWidth() and getHeight().
77
• To measure its dimensions, a view takes into
account its padding.
• The padding is expressed in pixels for the left,
top, right and bottom parts of the view.
• Padding can be used to offset the content of
the view by a specific amount of pixels.
78
• For instance, a left padding of 2 will push the
view's content by 2 pixels to the right of the
left edge.
• Padding can be set using the setPadding(int,
int, int, int) method and queried by calling
getPaddingLeft(), getPaddingTop(),
getPaddingRight() and getPaddingBottom().
79
• Even though a view can define a padding, it
does not provide any support for margins.
• However, view groups provide such a support.
Refer to ViewGroup and
ViewGroup.MarginLayoutParams for further
information.
• For more information about dimensions, see
Dimension Values.
80
• [Remember that in the graphical development
environment you can set properties.
• For the time being, you can think of the
information given above as general
background on properties.
• As noted a little while back, we hope to avoid
details like this as much as possible.]
81
• Common Layouts
• Each subclass of the ViewGroup class provides
a unique way to display the views you nest
within it.
• Below are some of the more common layout
types that are built into the Android platform.
82
• Linear Layout, Relative Layout, and Web View
83
• Note: Although you can nest one or more
layouts within another layout to acheive your
UI design, you should strive to keep your
layout hierarchy as shallow as possible.
• Your layout draws faster if it has fewer nested
layouts (a wide view hierarchy is better than a
deep view hierarchy).
84
• Linear Layout
• A layout that organizes its children into a
single horizontal or vertical row.
• It creates a scrollbar if the length of the
window exceeds the length of the screen.
85
• Relative Layout
• Enables you to specify the location of child
objects relative to each other (child A to the
left of child B) or to the parent (aligned to the
top of the parent).
• Web View
• Displays web pages.
86
• Building Layouts with an Adapter
• When the content for your layout is dynamic
or not pre-determined, you can use a layout
that subclasses AdapterView to populate the
layout with views at runtime.
• A subclass of the AdapterView class uses an
Adapter to bind data to its layout.
87
• The Adapter behaves as a middle-man
between the data source and the
AdapterView layout—the Adapter retrieves
the data (from a source such as an array or a
database query) and converts each entry into
a view that can be added into the
AdapterView layout.
88
• [This comes up in design patterns—and exists in
the Java API.
• Setting aside Android for the moment:
• Suppose you have an array of objects of the same
class, which each have some string value.
• Suppose your application contains a Table class,
where this class has had its cells defined
generically so they can be populated with
“anything”.
89
• Adaptation has to do with the process of
converting the set of string instance variable
values coming from the array of objects into a
set of objects/values which can populate the
cells in a row of the table.
• The same idea applies when trying to
populate the elements of a ViewGroup which
contains a well defined set of child Views.]
90
• Common layouts backed by an adapter
include: List View, Grid View
91
•
•
•
•
List View:
Displays a scrolling single column list.
Grid View:
Displays a scrolling grid of columns and rows.
92
• Filling an adapter view with data
• You can populate an AdapterView such as
ListView or GridView by binding the AdapterView
instance to an Adapter, which retrieves data from
an external source and creates a View that
represents each data entry.
• Android provides several subclasses of Adapter
that are useful for retrieving different kinds of
data and building views for an AdapterView. The
two most common adapters are: [ArrayAdapter,
SimpleCursorAdapter]
93
• ArrayAdapter
• Use this adapter when your data source is an
array.
• By default, ArrayAdapter creates a view for each
array item by calling toString() on each item and
placing the contents in a TextView.
• [Notice our friend toString() doing the conversion
or adaptation of an object and turning it into a
child TextView in an AdapterView.]
94
• For example, if you have an array of strings
you want to display in a ListView, initialize a
new ArrayAdapter using a constructor to
specify the layout for each string and the
string array:
•
ArrayAdapter adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
95
• The arguments for this constructor are:
• Your app Context
• The layout that contains a TextView for each
string in the array
• The string array
96
• Then simply call setAdapter() on your
ListView:
•
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
• [Recall the statements made earlier:
• You populate the AdapterView (simply) by
binding it to the adapter (which adapts some
data set).]
97
• To customize the appearance of each item you
can override the toString() method for the
objects in your array.
• Or, to create a view for each item that's
something other than a TextView (for
example, if you want an ImageView for each
array item), extend the ArrayAdapter class and
override getView() to return the type of view
you want for each item.
98
• [There is nothing cosmic about this comment.
• It just gets hard to see the forest for the trees
sometimes.
• All of the preceding information tells you this:
• The whole mechanism is set up by default to
display strings.
• A vanilla ListView consists of a bunch of
TextViews.]
99
• [The next subsection on the CursorAdapter is
included for completeness’ sake.
• But I have no intention of covering it in detail.
• That would require delving into
cursors…which haven’t been covered yet.
• Until we’ve covered more stuff on input
functions, adapting to cursors is off topic.]
100
• SimpleCursorAdapter
• Use this adapter when your data comes from a Cursor.
• When using SimpleCursorAdapter, you must specify a
layout to use for each row in the Cursor and which
columns in the Cursor should be inserted into which
views of the layout.
• For example, if you want to create a list of people's
names and phone numbers, you can perform a query
that returns a Cursor containing a row for each person
and columns for the names and numbers.
101
• You then create a string array specifying which
columns from the Cursor you want in the
layout for each result and an integer array
specifying the corresponding views that each
column should be placed:
•
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
102
• When you instantiate the
SimpleCursorAdapter, pass the layout to use
for each result, the Cursor containing the
results, and these two arrays:
•
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
103
• The SimpleCursorAdapter then creates a view for
each row in the Cursor using the provided layout
by inserting each fromColumns item into the
corresponding toViews view.
• If, during the course of your application's life, you
change the underlying data that is read by your
adapter, you should call notifyDataSetChanged().
This will notify the attached view that the data
has been changed and it should refresh itself.
104
• [The next section is kind of out of the blue.
• Like the foregoing, it’s included for
completeness’ sake.
• Here is a scenario:
• Suppose you wanted to populate a ListView
with buttons instead of text…
105
• Keep in mind that this section on adaptation
presupposes that you couldn’t completely define
a layout in advance.
• The buttons aren’t there and you can’t predefine
sendMessage() methods for them.
• You’re doing it “programmatically,” namely, when
your Java code is running.
• So at run time, you want to make some buttons
and you’d like them to have functionality.]
106
• Handling click events
• You can respond to click events on each item
in an AdapterView by implementing the
AdapterView.OnItemClickListener interface.
For example:
•
// Create a message handling object as an anonymous class.
private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// Do something in response to the click
}
};
listView.setOnItemClickListener(mMessageClickedHandler);
107
• [Notice that the foregoing example code used
the syntax for an anonymous listener.
• The event handling method in the listener is
onItemClick().
• In the coming sections, the use of listeners in
Android Java code will be covered in more
detail.]
108
8.4 Linear Layout
109
• Linear Layout
• LinearLayout is a view group that aligns all
children in a single direction, vertically or
horizontally.
• You can specify the layout direction with the
android:orientation attribute.
110
111
• All children of a LinearLayout are stacked one
after the other, so a vertical list will only have
one child per row, no matter how wide they
are, and a horizontal list will only be one row
high (the height of the tallest child, plus
padding).
• A LinearLayout respects margins between
children and the gravity (right, center, or left
alignment) of each child.
112
• Layout Weight
• LinearLayout also supports assigning a weight
to individual children with the
android:layout_weight attribute.
• This attribute assigns an "importance" value
to a view in terms of how much space is
should occupy on the screen.
• A larger weight value allows it to expand to fill
any remaining space in the parent view.
113
• Child views can specify a weight value, and
then any remaining space in the view group is
assigned to children in the proportion of their
declared weight.
• Default weight is zero.
114
• For example, if there are three text fields and
two of them declare a weight of 1, while the
other is given no weight, the third text field
without weight will not grow and will only
occupy the area required by its content.
• The other two will expand equally to fill the
space remaining after all three fields are
measured.
115
• If the third field is then given a weight of 2
(instead of 0), then it is now declared more
important than both the others, so it gets half
the total remaining space, while the first two
share the rest equally.
116
• Equally weighted children
• To create a linear layout in which each child
uses the same amount of space on the screen,
set the android:layout_height of each view to
"0dp" (for a vertical layout) or the
android:layout_width of each view to "0dp"
(for a horizontal layout).
• Then set the android:layout_weight of each
view to "1".
117
• Example
• Notice that the tutorials have mistakenly
named this Relative Layout, when it’s Linear
Layout, vertical
118
•
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="vertical" >
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/to" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/subject" />
<EditText
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top"
android:hint="@string/message" />
<Button
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="@string/send" />
</LinearLayout>
119
• For details about the attributes available to
each child view of a LinearLayout, see
LinearLayout.LayoutParams.
120
8.5 Relative Layout
121
• Relative Layout
• RelativeLayout is a view group that displays
child views in relative positions.
• The position of each view can be specified as
relative to sibling elements (such as to the
left-of or below another view) or in positions
relative to the parent RelativeLayout area
(such as aligned to the bottom, left of center).
122
123
• A RelativeLayout is a very powerful utility for
designing a user interface because it can
eliminate nested view groups and keep your
layout hierarchy flat, which improves
performance.
• If you find yourself using several nested
LinearLayout groups, you may be able to
replace them with a single RelativeLayout.
124
• Positioning Views
• RelativeLayout lets child views specify their
position relative to the parent view or to each
other (specified by ID).
• So you can align two elements by right border, or
make one below another, centered in the screen,
centered left, and so on.
• By default, all child views are drawn at the topleft of the layout, so you must define the position
of each view using the various layout properties
available from RelativeLayout.LayoutParams.
125
• Some of the many layout properties available
to views in a RelativeLayout include:
• android:layout_alignParentTop
• If "true", makes the top edge of this view
match the top edge of the parent.
android:layout_centerVertical
• If "true", centers this child vertically within its
parent.
126
• android:layout_below
• Positions the top edge of this view below the
view specified with a resource ID.
android:layout_toRightOf
• Positions the left edge of this view to the right
of the view specified with a resource ID.
• These are just a few examples.
• All layout attributes are documented at
RelativeLayout.LayoutParams.
127
• The value for each layout property is either a boolean
to enable a layout position relative to the parent
RelativeLayout or an ID that references another view in
the layout against which the view should be
positioned.
• In your XML layout, dependencies against other views
in the layout can be declared in any order. For example,
you can declare that "view1" be positioned below
"view2" even if "view2" is the last view declared in the
hierarchy.
• The example below demonstrates such a scenario.
128
• Example
129
• Each of the attributes that control the relative
position of each view are emphasized.
• [Note that this layout contains spinners.
• They haven’t been introduced yet, but they
will be in the next unit.]
130
•
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
<EditText
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/reminder" />
<Spinner
android:id="@+id/dates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/times" />
<Spinner
android:id="@id/times"
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_alignParentRight="true" />
<Button
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="@id/times"
android:layout_alignParentRight="true"
android:text="@string/done" />
</RelativeLayout>
131
• For details about all the layout attributes
available to each child view of a
RelativeLayout, see
RelativeLayout.LayoutParams.
132
8.6 List View
133
• List View
• ListView is a view group that displays a list of
scrollable items.
• The list items are automatically inserted to the
list using an Adapter that pulls content from a
source such as an array or database query and
converts each item result into a view that's
placed into the list.
• For an introduction to how you can dynamically
insert views using an adapter, read Building
Layouts with an Adapter.
134
135
• Using a Loader
• Using a CursorLoader is the standard way to
query a Cursor as an asynchronous task in order
to avoid blocking your app's main thread with the
query.
• When the CursorLoader receives the Cursor
result, the LoaderCallbacks receives a callback to
onLoadFinished(), which is where you update
your Adapter with the new Cursor and the list
view then displays the results.
136
• Although the CursorLoader APIs were first
introduced in Android 3.0 (API level 11), they
are also available in the Support Library so
that your app may use them while supporting
devices running Android 1.6 or higher.
• For more information about using a Loader to
asynchronously load data, see the Loaders
guide.
137
• Example
• The following example uses ListActivity, which
is an activity that includes a ListView as its
only layout element by default.
• It performs a query to the Contacts Provider
for a list of names and phone numbers.
• The activity implements the LoaderCallbacks
interface in order to use a CursorLoader that
dynamically loads the data for the list view.
138
• [Note that this is a lot of information.
• It would take some serious code reading to
figure out what’s going on.
• I probably won’t do this in class.
• It’s here for reference.]
139
• [If you’re interested, this is the kind of thing you
figure out as part of the assignment
• Or you could do this as part of your project.
• Note that one of the uses is in displaying the
results of db queries.
• By definition, you can’t say in advance how many
rows you’ll get.
• So this idea of being able to generate layout
contents programmatically is useful in advanced
settings.]
140
•
public class ListViewLoader extends ListActivity
implements LoaderManager.LoaderCallbacks<Cursor> {
// This is the Adapter being used to display the list's data
SimpleCursorAdapter mAdapter;
// These are the Contacts rows that we will retrieve
static final String[] PROJECTION = new String[]
{ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME};
// This is the select criteria
static final String SELECTION = "((" +
ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
ContactsContract.Data.DISPLAY_NAME + " != '' ))";
141
•
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a progress bar to display while the list loads
ProgressBar progressBar = new ProgressBar(this);
progressBar.setLayoutParams(new
LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, Gravity.CENTER));
progressBar.setIndeterminate(true);
getListView().setEmptyView(progressBar);
// Must add the progress bar to the root of the layout
ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
root.addView(progressBar);
// For the cursor adapter, specify which columns go into which views
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
int[] toViews = {android.R.id.text1}; // The TextView in
simple_list_item_1
// Create an empty adapter we will use to display the loaded data.
// We pass null for the cursor, then update it in onLoadFinished()
mAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, null,
fromColumns, toViews, 0);
setListAdapter(mAdapter);
}
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
142
•
// Called when a new Loader needs to be created
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
PROJECTION, SELECTION, null, null);
}
the
// Called when a previously created loader has finished loading
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing
}
// old cursor once we return.)
mAdapter.swapCursor(data);
// Called when a previously created loader is reset, making the data
unavailable
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Do something when a list item is clicked
}
143
• Note: Because this sample performs a query
on the Contacts Provider, if you want to try
this code, your app must request the
READ_CONTACTS permission in the manifest
file:
• <uses-permission
android:name="android.permission.READ_CONTACTS" />
144
• [Even though the main topic of the example is the
machinery for the list itself, I’m hardly trying to explain
it at all.
• However, I do want to bring the last method in the
code to your attention:
•
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Do something when a list item is clicked
}
• You can dynamically generate a list, and the elements
of the list can be responsive to mouse clicks.]
145
8.7 Grid View
146
• Grid View
• GridView is a ViewGroup that displays items in
a two-dimensional, scrollable grid.
• The grid items are automatically inserted to
the layout using a ListAdapter.
• For an introduction to how you can
dynamically insert views using an adapter,
read Building Layouts with an Adapter.
147
148
• Example
• In this tutorial, you'll create a grid of image
thumbnails.
• When an item is selected, a toast message will
display the position of the image.
149
• [Because of the order that I’m presenting things
in, the term Toast hasn’t been explained yet.
• This is from the API.
• “A toast is a view containing a quick little message
for the user.”
• In Java we saw the use of dialog boxes
• A toast isn’t even that complex, but the idea of a
simple, system supplied thing for supporting
interaction with the user is similar.]
150
• 1. Start a new project named HelloGridView.
• 2. Find some photos you'd like to use, or
download these sample images.
• Save the image files into the project's
res/drawable/ directory.
151
• 3. Open the res/layout/main.xml file and insert the following:
•
• <?xml version="1.0" encoding="utf-8"?>
<GridView
xmlns:android="http://schemas.android.com/apk
/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
152
•
•
•
•
This GridView will fill the entire screen.
The attributes are rather self explanatory.
[?]
For more information about valid attributes,
see the GridView reference.
153
• 4. Open HelloGridView.java and insert the following
code for the onCreate() method:
•
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
GridView gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int
position, long id) {
Toast.makeText(HelloGridView.this, "" + position,
Toast.LENGTH_SHORT).show();
}
});
}
154
• After the main.xml layout is set for the
content view, the GridView is captured from
the layout with findViewById(int).
• The setAdapter() method then sets a custom
adapter (ImageAdapter) as the source for all
items to be displayed in the grid.
• The ImageAdapter is created in the next step.
155
• To do something when an item in the grid is
clicked, the setOnItemClickListener() method is
passed a new AdapterView.OnItemClickListener.
• This anonymous instance defines the
onItemClick() callback method to show a Toast
that displays the index position (zero-based) of
the selected item (in a real world scenario, the
position could be used to get the full sized image
for some other task).
156
• 5. Create a new class called ImageAdapter that extends
BaseAdapter:
•
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
157
•
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
158
•
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.sample_2, R.drawable.sample_3,
R.drawable.sample_4, R.drawable.sample_5,
R.drawable.sample_6, R.drawable.sample_7,
R.drawable.sample_0, R.drawable.sample_1,
R.drawable.sample_2, R.drawable.sample_3,
R.drawable.sample_4, R.drawable.sample_5,
R.drawable.sample_6, R.drawable.sample_7,
R.drawable.sample_0, R.drawable.sample_1,
R.drawable.sample_2, R.drawable.sample_3,
R.drawable.sample_4, R.drawable.sample_5,
R.drawable.sample_6, R.drawable.sample_7
};
159
• First, this implements some required methods
inherited from BaseAdapter.
• The constructor and getCount() are selfexplanatory.
• Normally, getItem(int) should return the
actual object at the specified position in the
adapter, but it's ignored for this example.
• Likewise, getItemId(int) should return the row
id of the item, but it's not needed here.
160
• The first method necessary is getView().
• This method creates a new View for each image
added to the ImageAdapter.
• When this is called, a View is passed in, which is
normally a recycled object (at least after this has
been called once), so there's a check to see if the
object is null.
• If it is null, an ImageView is instantiated and
configured with desired properties for the image
presentation:
161
• setLayoutParams(ViewGroup.LayoutParams) sets the
height and width for the View—this ensures that, no
matter the size of the drawable, each image is resized
and cropped to fit in these dimensions, as appropriate.
• setScaleType(ImageView.ScaleType) declares that
images should be cropped toward the center (if
necessary).
• setPadding(int, int, int, int) defines the padding for all
sides. (Note that, if the images have different aspectratios, then less padding will cause more cropping of
the image if it does not match the dimensions given to
the ImageView.)
162
• If the View passed to getView() is not null, then
the local ImageView is initialized with the
recycled View object.
• At the end of the getView() method, the position
integer passed into the method is used to select
an image from the mThumbIds array, which is set
as the image resource for the ImageView.
• All that's left is to define the mThumbIds array of
drawable resources.
163
• 6. Run the application.
• Try experimenting with the behaviors of the
GridView and ImageView elements by
adjusting their properties.
• For example, instead of using
setLayoutParams(ViewGroup.LayoutParams),
try using setAdjustViewBounds(boolean).
164
Summary and Mission
• This set of overheads is the first one covering
material that you may choose to include as
part of part 2 of the second programming
assignment
• The general information about layouts might
be useful
• Most likely, though, you will actually end up
satisfying the assignment requirements with
items given in the following sets of overheads.
165
The End
166