M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@ -0,0 +1,113 @@
page.title=Binding to Data with AdapterView
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#FillingTheLayout">Filling the Layout with Data</a></li>
<li><a href="#HandlingUserSelections">Handling User Selections</a></li>
</ol>
<h2>Related tutorials</h2>
<ol>
<li><a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Spinner</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-listview.html">List View</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid View</a></li>
</ol>
</div>
</div>
<p>The {@link android.widget.AdapterView} is a ViewGroup subclass whose child Views are determined by an {@link android.widget.Adapter Adapter} that
binds to data of some type. AdapterView is useful whenever you need to display stored data (as opposed to resource strings or drawables) in your layout.</p>
<p>{@link android.widget.Gallery Gallery}, {@link android.widget.ListView ListView}, and {@link android.widget.Spinner Spinner} are examples of AdapterView subclasses that you can use to bind to a specific type of data and display it in a certain way. </p>
<p>AdapterView objects have two main responsibilities: </p>
<ul>
<li>Filling the layout with data
</li>
<li>Handling user selections
</li>
</ul>
<h2 id="FillingTheLayout">Filling the Layout with Data</h2>
<p>Inserting data into the layout is typically done by binding the AdapterView class to an {@link
android.widget.Adapter}, which retrieves data from an external source (perhaps a list that
the code supplies or query results from the device's database). </p>
<p>The following code sample does the following:</p>
<ol>
<li>Creates a {@link android.widget.Spinner Spinner} with an existing View and binds it to a new ArrayAdapter
that reads an array of colors from the local resources.</li>
<li>Creates another Spinner object from a View and binds it to a new SimpleCursorAdapter that will read
people's names from the device contacts (see {@link android.provider.Contacts.People}).</li>
</ol>
<pre>
// Get a Spinner and bind it to an ArrayAdapter that
// references a String array.
Spinner s1 = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.colors, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s1.setAdapter(adapter);
// Load a Spinner and bind it to a data query.
private static String[] PROJECTION = new String[] {
People._ID, People.NAME
};
Spinner s2 = (Spinner) findViewById(R.id.spinner2);
Cursor cur = managedQuery(People.CONTENT_URI, PROJECTION, null, null);
SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, // Use a template
// that displays a
// text view
cur, // Give the cursor to the list adapter
new String[] {People.NAME}, // Map the NAME column in the
// people database to...
new int[] {android.R.id.text1}); // The "text1" view defined in
// the XML template
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s2.setAdapter(adapter2);
</pre>
<p>Note that it is necessary to have the People._ID column in projection used with CursorAdapter
or else you will get an exception.</p>
<p>If, during the course of your application's life, you change the underlying data that is read by your Adapter,
you should call {@link android.widget.ArrayAdapter#notifyDataSetChanged()}. This will notify the attached View
that the data has been changed and it should refresh itself.</p>
<h2 id="HandlingUserSelections">Handling User Selections</h2>
<p>You handle the user's selection by setting the class's {@link
android.widget.AdapterView.OnItemClickListener} member to a listener and
catching the selection changes. </p>
<pre>
// 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)
{
// Display a messagebox.
Toast.makeText(mContext,"You've got an event",Toast.LENGTH_SHORT).show();
}
};
// Now hook into our object and set its onItemClickListener member
// to our class handler object.
mHistoryView = (ListView)findViewById(R.id.history);
mHistoryView.setOnItemClickListener(mMessageClickedHandler);
</pre>
<div class="special">
<p>For more discussion on how to create different AdapterViews, read the following tutorials:
<a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Hello Spinner</a>,
<a href="{@docRoot}resources/tutorials/views/hello-listview.html">Hello ListView</a>, and
<a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Hello GridView</a>.
</div>

View File

@ -0,0 +1,563 @@
page.title=Building Custom Components
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#basic">The Basic Approach</a></li>
<li><a href="#custom">Fully Customized Components</a></li>
<li><a href="#compound">Compound Controls</a></li>
<li><a href="#modifying">Modifying an Existing View Type</a></li>
</ol>
</div>
</div>
<p>Android offers a sophisticated and powerful componentized model for building your UI,
based on the fundamental layout classes: {@link android.view.View} and
{@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt
View and ViewGroup subclasses &mdash; called widgets and layouts, respectively &mdash;
that you can use to construct your UI.</p>
<p>A partial list of available widgets includes {@link android.widget.Button Button},
{@link android.widget.TextView TextView},
{@link android.widget.EditText EditText},
{@link android.widget.ListView ListView},
{@link android.widget.CheckBox CheckBox},
{@link android.widget.RadioButton RadioButton},
{@link android.widget.Gallery Gallery},
{@link android.widget.Spinner Spinner}, and the more special-purpose
{@link android.widget.AutoCompleteTextView AutoCompleteTextView},
{@link android.widget.ImageSwitcher ImageSwitcher}, and
{@link android.widget.TextSwitcher TextSwitcher}. </p>
<p>Among the layouts available are {@link android.widget.LinearLayout LinearLayout},
{@link android.widget.FrameLayout FrameLayout}, {@link android.widget.RelativeLayout RelativeLayout},
and others. For more examples, see <a href="layout-objects.html">Common Layout Objects</a>.</p>
<p>If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass.
If you only need to make small adjustments to an existing widget or layout, you can simply subclass
the widget or layout and override its methods.
</p>
<p>Creating your own View subclasses gives you precise control over the appearance and function
of a screen element. To give an idea of the control you get with custom views, here are some
examples of what you could do with them:</p>
<ul>
<li>
You could create a completely custom-rendered View type, for example a "volume
control" knob rendered using 2D graphics, and which resembles an
analog electronic control.
</li>
<li>
You could combine a group of View components into a new single component, perhaps
to make something like a ComboBox (a combination of popup list and free
entry text field), a dual-pane selector control (a left and right pane
with a list in each where you can re-assign which item is in which
list), and so on.
</li>
<li>
You could override the way that an EditText component is rendered on the screen
(the <a href="{@docRoot}resources/samples/NotePad/index.html">Notepad Tutorial</a> uses this to good effect,
to create a lined-notepad page).
</li>
<li>
You could capture other events like key presses and handle them in some custom
way (such as for a game).
</li>
</ul>
<p>
The sections below explain how to create custom Views and use them in your application.
For detailed reference information, see the {@link android.view.View} class. </p>
<h2 id="basic">The Basic Approach</h2>
<p>Here is a high level overview of what you need to know to get started in creating your own
View components:</p>
<ol>
<li>
Extend an existing {@link android.view.View View} class or subclass
with your own class.
</li>
<li>
Override some of the methods from the superclass. The superclass methods
to override start with '<code>on</code>', for
example, {@link android.view.View#onDraw onDraw()},
{@link android.view.View#onMeasure onMeasure()}, and
{@link android.view.View#onKeyDown onKeyDown()}.
This is similar to the <code>on...</code> events in {@link android.app.Activity Activity}
or {@link android.app.ListActivity ListActivity}
that you override for lifecycle and other functionality hooks.
<li>
Use your new extension class. Once completed, your new extension class
can be used in place of the view upon which it was based.
</li>
</ol>
<p class="note"><strong>Tip:</strong>
Extension classes can be defined as inner classes inside the activities
that use them. This is useful because it controls access to them but
isn't necessary (perhaps you want to create a new public View for
wider use in your application).
</p>
<h2 id="custom">Fully Customized Components</h2>
<p>
Fully customized components can be used to create graphical components that
appear however you wish. Perhaps a graphical VU
meter that looks like an old analog gauge, or a sing-a-long text view where
a bouncing ball moves along the words so you can sing along with a karaoke
machine. Either way, you want something that the built-in components just
won't do, no matter how you combine them.</p>
<p>Fortunately, you can easily create components that look and behave in any
way you like, limited perhaps only by your imagination, the size of the
screen, and the available processing power (remember that ultimately your
application might have to run on something with significantly less power
than your desktop workstation).</p>
<p>To create a fully customized component:</p>
<ol>
<li>
The most generic view you can extend is, unsurprisingly, {@link
android.view.View View}, so you will usually start by extending this to
create your new super component.
</li>
<li>
You can supply a constructor which can
take attributes and parameters from the XML, and you can also consume
your own such attributes and parameters (perhaps the color and range of
the VU meter, or the width and damping of the needle, etc.)
</li>
<li>
You will probably want to create your own event listeners,
property accessors and modifiers, and possibly more sophisticated
behavior in your component class as well.
</li>
<li>
You will almost certainly want to override <code>onMeasure()</code> and
are also likely to need to override <code>onDraw()</code> if you want
the component to show something. While both have default behavior,
the default <code>onDraw()</code> will do nothing, and the default
<code>onMeasure()</code> will always set a size of 100x100 &mdash; which is
probably not what you want.
</li>
<li>
Other <code>on...</code> methods may also be overridden as required.
</li>
</ol>
<h3>Extend <code>onDraw()</code> and <code>onMeasure()</code></h3>
<p>The <code>onDraw()</code> method delivers you a {@link android.graphics.Canvas Canvas}
upon which you can implement anything you want: 2D graphics, other standard or
custom components, styled text, or anything else you can think of.</p>
<p class="note"><strong>Note:</strong>
This does not apply to 3D graphics. If you want to
use 3D graphics, you must extend {@link android.view.SurfaceView SurfaceView}
instead of View, and draw from a separate thread. See the
GLSurfaceViewActivity sample
for details.</p>
<p><code>onMeasure()</code> is a little more involved. <code>onMeasure()</code>
is a critical piece of the rendering contract between your component and its
container. <code>onMeasure()</code> should be overridden to efficiently and
accurately report the measurements of its contained parts. This is made
slightly more complex by the requirements of limits from the parent
(which are passed in to the <code>onMeasure()</code> method) and by the
requirement to call the <code>setMeasuredDimension()</code> method with the
measured width and height once they have been calculated. If you fail to
call this method from an overridden <code>onMeasure()</code> method, the
result will be an exception at measurement time.</p>
<p>At a high level, implementing <code>onMeasure()</code> looks something
like this:</p>
<ol>
<li>
The overridden <code>onMeasure()</code> method is called with width and
height measure specifications (<code>widthMeasureSpec</code> and
<code>heightMeasureSpec</code> parameters, both are integer codes
representing dimensions) which should be treated as requirements for
the restrictions on the width and height measurements you should produce. A
full reference to the kind of restrictions these specifications can require
can be found in the reference documentation under {@link
android.view.View#onMeasure View.onMeasure(int, int)} (this reference
documentation does a pretty good job of explaining the whole measurement
operation as well).
</li>
<li>
Your component's <code>onMeasure()</code> method should calculate a
measurement width and height which will be required to render the
component. It should try to stay within the specifications passed in,
although it can choose to exceed them (in this case, the parent can
choose what to do, including clipping, scrolling, throwing an exception,
or asking the <code>onMeasure()</code> to try again, perhaps with
different measurement specifications).
</li>
<li>
Once the width and height are calculated, the <code>setMeasuredDimension(int
width, int height)</code> method must be called with the calculated
measurements. Failure to do this will result in an exception being
thrown.
</li>
</ol>
<p>
Here's a summary of some of the other standard methods that the framework calls on views:
</p>
<table border="2" width="85%" align="center" cellpadding="5">
<thead>
<tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
</thead>
<tbody>
<tr>
<td rowspan="2">Creation</td>
<td>Constructors</td>
<td>There is a form of the constructor that are called when the view
is created from code and a form that is called when the view is
inflated from a layout file. The second form should parse and apply
any attributes defined in the layout file.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onFinishInflate()}</code></td>
<td>Called after a view and all of its children has been inflated
from XML.</td>
</tr>
<tr>
<td rowspan="3">Layout</td>
<td><code>{@link android.view.View#onMeasure}</code></td>
<td>Called to determine the size requirements for this view and all
of its children.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onLayout}</code></td>
<td>Called when this view should assign a size and position to all
of its children.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onSizeChanged}</code></td>
<td>Called when the size of this view has changed.
</td>
</tr>
<tr>
<td>Drawing</td>
<td><code>{@link android.view.View#onDraw}</code></td>
<td>Called when the view should render its content.
</td>
</tr>
<tr>
<td rowspan="4">Event processing</td>
<td><code>{@link android.view.View#onKeyDown}</code></td>
<td>Called when a new key event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onKeyUp}</code></td>
<td>Called when a key up event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onTrackballEvent}</code></td>
<td>Called when a trackball motion event occurs.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onTouchEvent}</code></td>
<td>Called when a touch screen motion event occurs.
</td>
</tr>
<tr>
<td rowspan="2">Focus</td>
<td><code>{@link android.view.View#onFocusChanged}</code></td>
<td>Called when the view gains or loses focus.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onWindowFocusChanged}</code></td>
<td>Called when the window containing the view gains or loses focus.
</td>
</tr>
<tr>
<td rowspan="3">Attaching</td>
<td><code>{@link android.view.View#onAttachedToWindow()}</code></td>
<td>Called when the view is attached to a window.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onDetachedFromWindow}</code></td>
<td>Called when the view is detached from its window.
</td>
</tr>
<tr>
<td><code>{@link android.view.View#onWindowVisibilityChanged}</code></td>
<td>Called when the visibility of the window containing the view
has changed.
</td>
</tr>
</tbody>
</table>
<h3 id="customexample">A Custom View Example</h3>
<p>The CustomView sample in the
<a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a> provides an example
of a customized View. The custom View is defined in the
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a>
class.</p>
<p>The LabelView sample demonstrates a number of different aspects of custom components:</p>
<ul>
<li>Extending the View class for a completely custom component.</li>
<li>Parameterized constructor that takes the view inflation parameters
(parameters defined in the XML). Some of these are passed through to the
View superclass, but more importantly, there are some custom attributes defined
and used for LabelView.</li>
<li>Standard public methods of the type you would expect to see for a label
component, for example <code>setText()</code>, <code>setTextSize()</code>,
<code>setTextColor()</code> and so on.</li>
<li>An overridden <code>onMeasure</code> method to determine and set the
rendering size of the component. (Note that in LabelView, the real work is done
by a private <code>measureWidth()</code> method.)</li>
<li>An overridden <code>onDraw()</code> method to draw the label onto the
provided canvas.</li>
</ul>
<p>You can see some sample usages of the LabelView custom View in
<a href="{@docRoot}resources/samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a>
from the samples. In particular, you can see a mix of both <code>android:</code>
namespace parameters and custom <code>app:</code> namespace parameters. These
<code>app:</code> parameters are the custom ones that the LabelView recognizes
and works with, and are defined in a styleable inner class inside of the
samples R resources definition class.</p>
<h2 id="compound">Compound Controls
</h2>
<p>If you don't want to create a completely customized component, but instead
are looking to put together a reusable component that consists of a group of
existing controls, then creating a Compound Component (or Compound Control) might
fit the bill. In a nutshell, this brings together a number of more atomic
controls (or views) into a logical group of items that can be treated as a
single thing. For example, a Combo Box can be thought of as a
combination of a single line EditText field and an adjacent button with an attached
PopupList. If you press the button and select
something from the list, it populates the EditText field, but the user can
also type something directly into the EditText if they prefer.</p>
<p>In Android, there are actually two other Views readily available to do
this: {@link android.widget.Spinner Spinner} and
{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but
regardless, the concept of a Combo Box makes an easy-to-understand
example.</p>
<p>To create a compound component:</p>
<ol>
<li>
The usual starting point is a Layout of some kind, so create a class
that extends a Layout. Perhaps in the case of a Combo box we might use
a LinearLayout with horizontal orientation. Remember that other layouts
can be nested inside, so the compound component can be arbitrarily
complex and structured. Note that just like with an Activity, you can
use either the declarative (XML-based) approach to creating the
contained components, or you can nest them programmatically from your
code.
</li>
<li>
In the constructor for the new class, take whatever parameters the
superclass expects, and pass them through to the superclass constructor
first. Then you can set up the other views to use within your new
component; this is where you would create the EditText field and the
PopupList. Note that you also might introduce your own attributes and
parameters into the XML that can be pulled out and used by your
constructor.
</li>
<li>
You can also create listeners for events that your contained views might
generate, for example, a listener method for the List Item Click Listener
to update the contents of the EditText if a list selection is made.
</li>
<li>
You might also create your own properties with accessors and modifiers,
for example, allow the EditText value to be set initially in the
component and query for its contents when needed.
</li>
<li>
In the case of extending a Layout, you don't need to override the
<code>onDraw()</code> and <code>onMeasure()</code> methods since the
layout will have default behavior that will likely work just fine. However,
you can still override them if you need to.
</li>
<li>
You might override other <code>on...</code> methods, like
<code>onKeyDown()</code>, to perhaps choose certain default values from
the popup list of a combo box when a certain key is pressed.
</li>
</ol>
<p>
To summarize, the use of a Layout as the basis for a Custom Control has a
number of advantages, including:</p>
<ul>
<li>
You can specify the layout using the declarative XML files just like
with an activity screen, or you can create views programmatically and
nest them into the layout from your code.
</li>
<li>
The <code>onDraw()</code> and <code>onMeasure()</code> methods (plus
most of the other <code>on...</code> methods) will likely have suitable behavior so
you don't have to override them.
</li>
<li>
In the end, you can very quickly construct arbitrarily complex compound
views and re-use them as if they were a single component.
</li>
</ul>
<h4>Examples of Compound Controls</h4>
<p>In the API Demos project
that comes with the SDK, there are two List
examples &mdash; Example 4 and Example 6 under Views/Lists demonstrate a
SpeechView which extends LinearLayout to make a component for displaying
Speech quotes. The corresponding classes in the sample code are
<code>List4.java</code> and <code>List6.java</code>.</p>
<h2 id="modifying">Modifying an Existing View Type</h2>
<p>There is an even easier option for creating a custom View which is
useful in certain circumstances. If there is a component that is already very
similar to what you want, you can simply extend that component and just
override the behavior that you want to change. You can do all of the things
you would do with a fully customized component, but by starting with a more
specialized class in the View hierarchy, you can also get a lot of behavior for
free that probably does exactly what you want.</p>
<p>For example, the SDK includes a <a
href="{@docRoot}resources/samples/NotePad/index.html">NotePad application</a> in the
samples. This demonstrates many aspects of using the Android platform, among
them is extending an EditText View to make a lined notepad. This is not a
perfect example, and the APIs for doing this might change from this early
preview, but it does demonstrate the principles.</p>
<p>If you haven't done so already, import the
NotePad sample into Eclipse (or
just look at the source using the link provided). In particular look at the definition of
<code>MyEditText</code> in the <a
href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a>
file.</p>
<p>Some points to note here</p>
<ol>
<li>
<strong>The Definition</strong>
<p>The class is defined with the following line:<br/>
<code>public static class MyEditText extends EditText</code></p>
<ul>
<li>
It is defined as an inner class within the <code>NoteEditor</code>
activity, but it is public so that it could be accessed as
<code>NoteEditor.MyEditText</code> from outside of the <code>NoteEditor</code>
class if desired.
</li>
<li>
It is <code>static</code>, meaning it does not generate the so-called
"synthetic methods" that allow it to access data from the parent
class, which in turn means that it really behaves as a separate
class rather than something strongly related to <code>NoteEditor</code>.
This is a cleaner way to create inner classes if they do not need
access to state from the outer class, keeps the generated class
small, and allows it to be used easily from other classes.
</li>
<li>
It extends <code>EditText</code>, which is the View we have chosen to
customize in this case. When we are finished, the new class will be
able to substitute for a normal <code>EditText</code> view.
</li>
</ul>
</li>
<li>
<strong>Class Initialization</strong>
<p>As always, the super is called first. Furthermore,
this is not a default constructor, but a parameterized one. The
EditText is created with these parameters when it is inflated from an
XML layout file, thus, our constructor needs to both take them and pass them
to the superclass constructor as well.</p>
</li>
<li>
<strong>Overridden Methods</strong>
<p>In this example, there is only one method to be overridden:
<code>onDraw()</code> &mdash; but there could easily be others needed when you
create your own custom components.</p>
<p>For the NotePad sample, overriding the <code>onDraw()</code> method allows
us to paint the blue lines on the <code>EditText</code> view canvas (the
canvas is passed into the overridden <code>onDraw()</code> method). The
super.onDraw() method is called before the method ends. The
superclass method should be invoked, but in this case, we do it at the
end after we have painted the lines we want to include.</p>
<li>
<strong>Use the Custom Component</strong>
<p>We now have our custom component, but how can we use it? In the
NotePad example, the custom component is used directly from the
declarative layout, so take a look at <code>note_editor.xml</code> in the
<code>res/layout</code> folder.</p>
<pre>
&lt;view
class=&quot;com.android.notepad.NoteEditor$MyEditText&quot;
id=&quot;&#64;+id/note&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:background=&quot;&#64;android:drawable/empty&quot;
android:padding=&quot;10dip&quot;
android:scrollbars=&quot;vertical&quot;
android:fadingEdge=&quot;vertical&quot; /&gt;
</pre>
<ul>
<li>
The custom component is created as a generic view in the XML, and
the class is specified using the full package. Note also that the
inner class we defined is referenced using the
<code>NoteEditor$MyEditText</code> notation which is a standard way to
refer to inner classes in the Java programming language.
<p>If your custom View component is not defined as an inner class, then you can,
alternatively, declare the View component
with the XML element name, and exclude the <code>class</code> attribute. For example:</p>
<pre>
&lt;com.android.notepad.MyEditText
id=&quot;&#64;+id/note&quot;
... />
</pre>
<p>Notice that the <code>MyEditText</code> class is now a separate class file. When the class
is nested in the <code>NoteEditor</code> class, this technique will not work.</p>
</li>
<li>
The other attributes and parameters in the definition are the ones
passed into the custom component constructor, and then passed
through to the EditText constructor, so they are the same
parameters that you would use for an EditText view. Note that it is
possible to add your own parameters as well, and we will touch on
this again below.
</li>
</ul>
</li>
</ol>
<p>And that's all there is to it. Admittedly this is a simple case, but
that's the point &mdash; creating custom components is only as complicated as you
need it to be.</p>
<p>A more sophisticated component may override even more <code>on...</code> methods and
introduce some of its own helper methods, substantially customizing its properties and
behavior. The only limit is your imagination and what you need the component to
do.</p>

View File

@ -0,0 +1,299 @@
page.title=Declaring Layout
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#write">Write the XML</a></li>
<li><a href="#load">Load the XML Resource</a></li>
<li><a href="#attributes">Attributes</a>
<ol>
<li><a href="#id">ID</a></li>
<li><a href="#layout-params">Layout Parameters</a></li>
</ol>
</li>
<li><a href="#Position">Position</a></li>
<li><a href="#SizePaddingMargins">Size, Padding and Margins</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.view.ViewGroup.LayoutParams}</li>
</ol>
</div>
</div>
<p>Your layout is the architecture for the user interface in an Activity.
It defines the layout structure and holds all the elements that appear to the user.
You can declare your layout in two ways:</p>
<ul>
<li><strong>Declare UI elements in XML</strong>. Android provides a straightforward XML
vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts.</li>
<li><strong>Instantiate layout elements at runtime</strong>. Your
application can create View and ViewGroup objects (and manipulate their properties) programmatically. </li>
</ul>
<p>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. </p>
<div class="sidebox-wrapper">
<div class="sidebox">
<ul>
<li>The <a href="{@docRoot}sdk/eclipse-adt.html">ADT
Plugin for Eclipse</a> offers a layout preview of your XML &mdash;
with the XML file opened, select the <strong>Layout</strong> tab.</li>
<li>You should also try the
<a href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">Hierarchy Viewer</a> tool,
for debugging layouts &mdash; it reveals layout property values,
draws wireframes with padding/margin indicators, and full rendered views while
you debug on the emulator or device.</li>
<li>The <a href="{@docRoot}guide/developing/tools/layoutopt.html">layoutopt</a> tool lets
you quickly analyze your layouts and hierarchies for inefficiencies or other problems.</li>
</div>
</div>
<p>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. 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. If you're
interested in instantiating View objects at runtime, refer to the {@link android.view.ViewGroup} and
{@link android.view.View} class references.</p>
<p>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. However, note that not all vocabulary is identical. In some cases, there are slight naming differences. For
example, the EditText element has a <code>text</code> attribute that corresponds to
<code>EditText.setText()</code>. </p>
<p class="note"><strong>Tip:</strong> Learn more about different layout types in <a href="{@docRoot}guide/topics/ui/layout-objects.html">Common
Layout Objects</a>. There are also a collection of tutorials on building various layouts in the
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a> tutorial guide.</p>
<h2 id="write">Write the XML</h2>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>For your convenience, the API reference documentation for UI related classes
lists the available XML attributes that correspond to the class methods, including inherited
attributes.</p>
<p>To learn more about the available XML elements and attributes, as well as the format of the XML file, see <a
href="{@docRoot}guide/topics/resources/available-resources.html#layoutresources">Layout Resources</a>.</p>
</div>
</div>
<p>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 &mdash; with a series of nested elements. </p>
<p>Each layout file must contain exactly one root element, which must be a View or ViewGroup object. 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 {@link android.widget.LinearLayout}
to hold a {@link android.widget.TextView} and a {@link android.widget.Button}:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>After you've declared your layout in XML, save the file with the <code>.xml</code> extension,
in your Android project's <code>res/layout/</code> directory, so it will properly compile. </p>
<p>We'll discuss each of the attributes shown here a little later.</p>
<h2 id="load">Load the XML Resource</h2>
<p>When you compile your application, each XML layout file is compiled into a
{@link android.view.View} resource. You should load the layout resource from your application code, in your
{@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} callback implementation.
Do so by calling <code>{@link android.app.Activity#setContentView(int) setContentView()}</code>,
passing it the reference to your layout resource in the form of:
<code>R.layout.<em>layout_file_name</em></code>
For example, if your XML layout is saved as <code>main_layout.xml</code>, you would load it
for your Activity like so:</p>
<pre>
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView.(R.layout.main_layout);
}
</pre>
<p>The <code>onCreate()</code> callback method in your Activity is called by the Android framework when
your Activity is launched (see the discussion on Lifecycles, in the
<a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Application Fundamentals</a>, for more on this).</p>
<h2 id="attributes">Attributes</h2>
<p>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 <code>textSize</code>
attribute), but these attributes are also inherited by any View objects that may extend this class.
Some are common to all View objects, because they are inherited from the root View class (like
the <code>id</code> 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.</p>
<h3 id="id">ID</h3>
<p>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 <code>id</code> attribute.
This is an XML attribute common to all View objects
(defined by the {@link android.view.View} class) and you will use it very often.
The syntax for an ID, inside an XML tag is:</p>
<pre>android:id="&#64;+id/my_button"</pre>
<p>The at-symbol (&#64;) 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 <code>R.java</code> file). 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 <code>android</code> package namespace, like so:</p>
<pre>android:id="&#64;android:id/empty"</pre>
<p>With the <code>android</code> package namespace in place, we're now referencing an ID from the <code>android.R</code>
resources class, rather than the local resources class.</p>
<p>In order to create views and reference them from the application, a common pattern is to:</p>
<ol>
<li>Define a view/widget in the layout file and assign it a unique ID:
<pre>
&lt;Button android:id="&#64;+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&#64;string/my_button_text"/>
</pre>
</li>
<li>Then create an instance of the view object and capture it from the layout
(typically in the <code>{@link android.app.Activity#onCreate(Bundle) onCreate()}</code> method):
<pre>
Button myButton = (Button) findViewById(R.id.my_button);
</pre>
</li>
</ol>
<p>Defining IDs for view objects is important when creating a {@link android.widget.RelativeLayout}.
In a relative layout, sibling views can define their layout relative to another sibling view,
which is referenced by the unique ID.</p>
<p>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).</p>
<h3 id="layout-params">Layout Parameters</h3>
<p>XML layout attributes named <code>layout_<em>something</em></code> define
layout parameters for the View that are appropriate for the ViewGroup in which it resides.</p>
<p>Every ViewGroup class implements a nested class that extends {@link
android.view.ViewGroup.LayoutParams}. This subclass
contains property types that define the size and position for each child view, as
appropriate for the view group. As you can see in the figure below, the parent
view group defines layout parameters for each child view (including the child view group).</p>
<img src="{@docRoot}images/layoutparams.png" alt="" height="300" align="center"/>
<p>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. </p>
<p>All view groups include a width and height (<code>layout_width</code> and
<code>layout_height</code>), and each view is required to define them. Many
LayoutParams also include optional margins and borders. <p>
<p>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: </p>
<ul>
<li><var>wrap_content</var> tells your view to size itself to the dimensions
required by its content</li>
<li><var>fill_parent</var> (renamed <var>match_parent</var> in API Level 8)
tells your view to become as big as its parent view group will allow.</li>
</ul>
<p>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 (<var>dp</var>), <var>wrap_content</var>, or
<var>fill_parent</var>, 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
<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
Available Resources</a> document.</p>
<h2 id="Position">Layout Position</h2>
<p>
The geometry of a view is that of a rectangle. A view has a location,
expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
two dimensions, expressed as a width and a height. The unit for location
and dimensions is the pixel.
</p>
<p>
It is possible to retrieve the location of a view by invoking the methods
{@link android.view.View#getLeft()} and {@link android.view.View#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. 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.
</p>
<p>
In addition, several convenience methods are offered to avoid unnecessary
computations, namely {@link android.view.View#getRight()} and {@link android.view.View#getBottom()}.
These methods return the coordinates of the right and bottom edges of the
rectangle representing the view. For instance, calling {@link android.view.View#getRight()}
is similar to the following computation: <code>getLeft() + getWidth()</code>.
</p>
<h2 id="SizePaddingMargins">Size, Padding and Margins</h2>
<p>
The size of a view is expressed with a width and a height. A view actually
possess two pairs of width and height values.
</p>
<p>
The first pair is known as <em>measured width</em> and
<em>measured height</em>. These dimensions define how big a view wants to be
within its parent. The
measured dimensions can be obtained by calling {@link android.view.View#getMeasuredWidth()}
and {@link android.view.View#getMeasuredHeight()}.
</p>
<p>
The second pair is simply known as <em>width</em> and <em>height</em>, or
sometimes <em>drawing width</em> and <em>drawing height</em>. 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
{@link android.view.View#getWidth()} and {@link android.view.View#getHeight()}.
</p>
<p>
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. 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
{@link android.view.View#setPadding(int, int, int, int)} method and queried by calling
{@link android.view.View#getPaddingLeft()}, {@link android.view.View#getPaddingTop()},
{@link android.view.View#getPaddingRight()} and {@link android.view.View#getPaddingBottom()}.
</p>
<p>
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
{@link android.view.ViewGroup} and
{@link android.view.ViewGroup.MarginLayoutParams} for further information.
</p>
<p>For more information about dimensions, see <a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">Dimension Values</a>.</p>

View File

@ -0,0 +1,651 @@
page.title=Creating Dialogs
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#ShowingADialog">Showing a Dialog</a></li>
<li><a href="#DismissingADialog">Dismissing a Dialog</a></li>
<li><a href="#AlertDialog">Creating an AlertDialog</a>
<ol>
<li><a href="#AddingButtons">Adding buttons</a></li>
<li><a href="#AddingAList">Adding a list</a></li>
</ol>
</li>
<li><a href="#ProgressDialog">Creating a ProgressDialog</a>
<ol>
<li><a href="#ShowingAProgressBar">Showing a progress bar</a></li>
</ol>
</li>
<li><a href="#CustomDialog">Creating a Custom Dialog</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.Dialog}</li>
</ol>
</div>
</div>
<p>A dialog is usually a small window that appears in front of the current Activity.
The underlying Activity loses focus and the dialog accepts all user interaction.
Dialogs are normally used
for notifications and short activities that directly relate to the application in progress.</p>
<p>The Android API supports the following types of {@link android.app.Dialog} objects:</p>
<dl>
<dt>{@link android.app.AlertDialog}</dt>
<dd>A dialog that can manage zero, one, two, or three buttons, and/or a list of
selectable items that can include checkboxes or radio buttons. The AlertDialog
is capable of constructing most dialog user interfaces and is the suggested dialog type.
See <a href="#AlertDialog">Creating an AlertDialog</a> below.</dd>
<dt>{@link android.app.ProgressDialog}</dt>
<dd>A dialog that displays a progress wheel or progress bar. Because it's an extension of
the AlertDialog, it also supports buttons.
See <a href="#ProgressDialog">Creating a ProgressDialog</a> below.</dd>
<dt>{@link android.app.DatePickerDialog}</dt>
<dd>A dialog that allows the user to select a date. See the
<a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello DatePicker</a> tutorial.</dd>
<dt>{@link android.app.TimePickerDialog}</dt>
<dd>A dialog that allows the user to select a time. See the
<a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello TimePicker</a> tutorial.</dd>
</dl>
<p>If you would like to customize your own dialog, you can extend the
base {@link android.app.Dialog} object or any of the subclasses listed above and define a new layout.
See the section on <a href="#CustomDialog">Creating a Custom Dialog</a> below.</p>
<h2 id="ShowingADialog">Showing a Dialog</h2>
<p>A dialog is always created and displayed as a part of an {@link android.app.Activity}.
You should normally create dialogs from within your Activity's
{@link android.app.Activity#onCreateDialog(int)} callback method.
When you use this callback, the Android system automatically manages the state of
each dialog and hooks them to the Activity, effectively making it the "owner" of each dialog.
As such, each dialog inherits certain properties from the Activity. For example, when a dialog
is open, the Menu key reveals the options menu defined for the Activity and the volume
keys modify the audio stream used by the Activity.</p>
<p class="note"><strong>Note:</strong> If you decide to create a dialog outside of the
<code>onCreateDialog()</code> method, it will not be attached to an Activity. You can, however,
attach it to an Activity with {@link android.app.Dialog#setOwnerActivity(Activity)}.</p>
<p>When you want to show a dialog, call
{@link android.app.Activity#showDialog(int)} and pass it an integer that uniquely identifies the
dialog that you want to display.</p>
<p>When a dialog is requested for the first time, Android calls
{@link android.app.Activity#onCreateDialog(int)} from your Activity, which is
where you should instantiate the {@link android.app.Dialog}. This callback method
is passed the same ID that you passed to {@link android.app.Activity#showDialog(int)}.
After you create the Dialog, return the object at the end of the method.</p>
<p>Before the dialog is displayed, Android also calls the optional callback method
{@link android.app.Activity#onPrepareDialog(int,Dialog)}. Define this method if you want to change
any properties of the dialog each time it is opened. This method is called
every time a dialog is opened, whereas {@link android.app.Activity#onCreateDialog(int)} is only
called the very first time a dialog is opened. If you don't define
{@link android.app.Activity#onPrepareDialog(int,Dialog) onPrepareDialog()}, then the dialog will
remain the same as it was the previous time it was opened. This method is also passed the dialog's
ID, along with the Dialog object you created in {@link android.app.Activity#onCreateDialog(int)
onCreateDialog()}.</p>
<p>The best way to define the {@link android.app.Activity#onCreateDialog(int)} and
{@link android.app.Activity#onPrepareDialog(int,Dialog)} callback methods is with a
<em>switch</em> statement that checks the <var>id</var> parameter that's passed into the method.
Each <em>case</em> should check for a unique dialog ID and then create and define the respective Dialog.
For example, imagine a game that uses two different dialogs: one to indicate that the game
has paused and another to indicate that the game is over. First, define an integer ID for
each dialog:</p>
<pre>
static final int DIALOG_PAUSED_ID = 0;
static final int DIALOG_GAMEOVER_ID = 1;
</pre>
<p>Then, define the {@link android.app.Activity#onCreateDialog(int)} callback with a
switch case for each ID:</p>
<pre>
protected Dialog onCreateDialog(int id) {
Dialog dialog;
switch(id) {
case DIALOG_PAUSED_ID:
// do the work to define the pause Dialog
break;
case DIALOG_GAMEOVER_ID:
// do the work to define the game over Dialog
break;
default:
dialog = null;
}
return dialog;
}
</pre>
<p class="note"><strong>Note:</strong> In this example, there's no code inside
the case statements because the procedure for defining your Dialog is outside the scope
of this section. See the section below about <a href="#AlertDialog">Creating an AlertDialog</a>,
offers code suitable for this example.</p>
<p>When it's time to show one of the dialogs, call {@link android.app.Activity#showDialog(int)}
with the ID of a dialog:</p>
<pre>
showDialog(DIALOG_PAUSED_ID);
</pre>
<h2 id="DismissingADialog">Dismissing a Dialog</h2>
<p>When you're ready to close your dialog, you can dismiss it by calling
{@link android.app.Dialog#dismiss()} on the Dialog object.
If necessary, you can also call {@link android.app.Activity#dismissDialog(int)} from the
Activity, which effectively calls {@link android.app.Dialog#dismiss()} on the
Dialog for you.</p>
<p>If you are using {@link android.app.Activity#onCreateDialog(int)} to manage the state
of your dialogs (as discussed in the previous section), then every time your dialog is
dismissed, the state of the Dialog
object is retained by the Activity. If you decide that you will no longer need this object or
it's important that the state is cleared, then you should call
{@link android.app.Activity#removeDialog(int)}. This will remove any internal references
to the object and if the dialog is showing, it will dismiss it.</p>
<h3>Using dismiss listeners</h3>
<p>If you'd like your application to perform some procedures the moment that a dialog is dismissed,
then you should attach an on-dismiss listener to your Dialog.</p>
<p>First define the {@link android.content.DialogInterface.OnDismissListener} interface.
This interface has just one method,
{@link android.content.DialogInterface.OnDismissListener#onDismiss(DialogInterface)}, which
will be called when the dialog is dismissed.
Then simply pass your OnDismissListener implementation to
{@link android.app.Dialog#setOnDismissListener(DialogInterface.OnDismissListener)
setOnDismissListener()}.</p>
<p>However, note that dialogs can also be "cancelled." This is a special case that indicates
the dialog was explicitly cancelled by the user. This will occur if the user presses the
"back" button to close the dialog, or if the dialog explicitly calls {@link android.app.Dialog#cancel()}
(perhaps from a "Cancel" button in the dialog). When a dialog is cancelled,
the OnDismissListener will still be notified, but if you'd like to be informed that the dialog
was explicitly cancelled (and not dismissed normally), then you should register
an {@link android.content.DialogInterface.OnCancelListener} with
{@link android.app.Dialog#setOnCancelListener(DialogInterface.OnCancelListener)
setOnCancelListener()}.</p>
<h2 id="AlertDialog">Creating an AlertDialog</h2>
<p>An {@link android.app.AlertDialog} is an extension of the {@link android.app.Dialog}
class. It is capable of constructing most dialog user interfaces and is the suggested dialog type.
You should use it for dialogs that use any of the following features:</p>
<ul>
<li>A title</li>
<li>A text message</li>
<li>One, two, or three buttons</li>
<li>A list of selectable items (with optional checkboxes or radio buttons)</li>
</ul>
<p>To create an AlertDialog, use the {@link android.app.AlertDialog.Builder} subclass.
Get a Builder with {@link android.app.AlertDialog.Builder#AlertDialog.Builder(Context)} and
then use the class's public methods to define all of the
AlertDialog properties. After you're done with the Builder, retrieve the
AlertDialog object with {@link android.app.AlertDialog.Builder#create()}.</p>
<p>The following topics show how to define various properties of the AlertDialog using the
AlertDialog.Builder class. If you use any of the following sample code inside your
{@link android.app.Activity#onCreateDialog(int) onCreateDialog()} callback method,
you can return the resulting Dialog object to display the dialog.</p>
<h3 id="AddingButtons">Adding buttons</h3>
<img src="{@docRoot}images/dialog_buttons.png" alt="" style="float:right" />
<p>To create an AlertDialog with side-by-side buttons like the one shown in the screenshot to the right,
use the <code>set...Button()</code> methods:</p>
<pre>
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MyActivity.this.finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
</pre>
<p>First, add a message for the dialog with
{@link android.app.AlertDialog.Builder#setMessage(CharSequence)}. Then, begin
method-chaining and set the dialog
to be <em>not cancelable</em> (so the user cannot close the dialog with the back button)
with {@link android.app.AlertDialog.Builder#setCancelable(boolean)}. For each button,
use one of the <code>set...Button()</code> methods, such as
{@link android.app.AlertDialog.Builder#setPositiveButton(CharSequence,DialogInterface.OnClickListener)
setPositiveButton()}, that accepts the name for the button and a
{@link android.content.DialogInterface.OnClickListener} that defines the action to take
when the user selects the button.</p>
<p class="note"><strong>Note:</strong> You can only add one of each button type to the
AlertDialog. That is, you cannot have more than one "positive" button. This limits the number
of possible buttons to three: positive, neutral, and negative. These names are technically irrelevant to the
actual functionality of your buttons, but should help you keep track of which one does what.</p>
<h3 id="AddingAList">Adding a list</h3>
<img src="{@docRoot}images/dialog_list.png" alt="" style="float:right" />
<p>To create an AlertDialog with a list of selectable items like the one shown to the right,
use the <code>setItems()</code> method:</p>
<pre>
final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a color");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert = builder.create();
</pre>
<p>First, add a title to the dialog with
{@link android.app.AlertDialog.Builder#setTitle(CharSequence)}.
Then, add a list of selectable items with
{@link android.app.AlertDialog.Builder#setItems(CharSequence[],DialogInterface.OnClickListener)
setItems()}, which accepts the array of items to display and a
{@link android.content.DialogInterface.OnClickListener} that defines the action to take
when the user selects an item.</p>
<h4>Adding checkboxes and radio buttons</h4>
<img src="{@docRoot}images/dialog_singlechoicelist.png" alt="" style="float:right" />
<p>To create a list of multiple-choice items (checkboxes) or
single-choice items (radio buttons) inside the dialog, use the
{@link android.app.AlertDialog.Builder#setMultiChoiceItems(Cursor,String,String,
DialogInterface.OnMultiChoiceClickListener) setMultiChoiceItems()} and
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()} methods, respectively.
If you create one of these selectable lists in the
{@link android.app.Activity#onCreateDialog(int) onCreateDialog()} callback method,
Android manages the state of the list for you. As long as the Activity is active,
the dialog remembers the items that were previously selected, but when the user exits the
Activity, the selection is lost.
<p class="note"><strong>Note:</strong> To save the selection when the user leaves or
pauses the Activity, you must properly save and restore the setting throughout
the <a href="{@docRoot}guide/topics/fundamentals.html#lcycles">Activity Lifecycle</a>.
To permanently save the selections, even when the Activity process is completely shutdown,
you need to save the settings
with one of the <a href="{@docRoot}guide/topics/data/data-storage.html">Data
Storage</a> techniques.</p>
<p>To create an AlertDialog with a list of single-choice items like the one shown to the right,
use the same code from the previous example, but replace the <code>setItems()</code> method with
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(int,int,DialogInterface.OnClickListener)
setSingleChoiceItems()}:</p>
<pre>
final CharSequence[] items = {"Red", "Green", "Blue"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a color");
builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
}
});
AlertDialog alert = builder.create();
</pre>
<p>The second parameter in the
{@link android.app.AlertDialog.Builder#setSingleChoiceItems(CharSequence[],int,DialogInterface.OnClickListener)
setSingleChoiceItems()} method is an integer value for the <var>checkedItem</var>, which indicates the
zero-based list position of the default selected item. Use "-1" to indicate that no item should be
selected by default.</p>
<h2 id="ProgressDialog">Creating a ProgressDialog</h2>
<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" />
<p>A {@link android.app.ProgressDialog} is an extension of the {@link android.app.AlertDialog}
class that can display a progress animation in the form of a spinning wheel, for a task with
progress that's undefined, or a progress bar, for a task that has a defined progression.
The dialog can also provide buttons, such as one to cancel a download.</p>
<p>Opening a progress dialog can be as simple as calling
{@link android.app.ProgressDialog#show(Context,CharSequence,CharSequence)
ProgressDialog.show()}. For example, the progress dialog shown to the right can be
easily achieved without managing the dialog through the
{@link android.app.Activity#onCreateDialog(int)} callback,
as shown here:</p>
<pre>
ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "",
"Loading. Please wait...", true);
</pre>
<p>The first parameter is the application {@link android.content.Context},
the second is a title for the dialog (left empty), the third is the message,
and the last parameter is whether the progress
is indeterminate (this is only relevant when creating a progress bar, which is
discussed in the next section).
</p>
<p>The default style of a progress dialog is the spinning wheel.
If you want to create a progress bar that shows the loading progress with granularity,
some more code is required, as discussed in the next section.</p>
<h3 id="ShowingAProgressBar">Showing a progress bar</h3>
<img src="/images/dialog_progress_bar.png" alt="" style="float:right" />
<p>To show the progression with an animated progress bar:</p>
<ol>
<li>Initialize the
ProgressDialog with the class constructor,
{@link android.app.ProgressDialog#ProgressDialog(Context)}.</li>
<li>Set the progress style to "STYLE_HORIZONTAL" with
{@link android.app.ProgressDialog#setProgressStyle(int)} and
set any other properties, such as the message.</li>
<li>When you're ready to show the dialog, call
{@link android.app.Dialog#show()} or return the ProgressDialog from the
{@link android.app.Activity#onCreateDialog(int)} callback.</li>
<li>You can increment the amount of progress displayed
in the bar by calling either {@link android.app.ProgressDialog#setProgress(int)} with a value for
the total percentage completed so far or {@link android.app.ProgressDialog#incrementProgressBy(int)}
with an incremental value to add to the total percentage completed so far.</li>
</ol>
<p>For example, your setup might look like this:</p>
<pre>
ProgressDialog progressDialog;
progressDialog = new ProgressDialog(mContext);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
</pre>
<p>The setup is simple. Most of the code needed to create a progress dialog is actually
involved in the process that updates it. You might find that it's
necessary to create a second thread in your application for this work and then report the progress
back to the Activity's UI thread with a {@link android.os.Handler} object.
If you're not familiar with using additional
threads with a Handler, see the example Activity below that uses a second thread to
increment a progress dialog managed by the Activity.</p>
<script type="text/javascript">
function toggleDiv(link) {
var toggleable = $(link).parent();
if (toggleable.hasClass("closed")) {
$(".toggleme", toggleable).slideDown("fast");
toggleable.removeClass("closed");
toggleable.addClass("open");
$(".toggle-img", toggleable).attr("title", "hide").attr("src", "/assets/images/triangle-opened.png");
} else {
$(".toggleme", toggleable).slideUp("fast");
toggleable.removeClass("open");
toggleable.addClass("closed");
$(".toggle-img", toggleable).attr("title", "show").attr("src", "/assets/images/triangle-closed.png");
}
return false;
}
</script>
<style>
.toggleme {
padding:0 0 1px 0;
}
.toggleable a {
text-decoration:none;
}
.toggleable.closed .toggleme {
display:none;
}
#jd-content .toggle-img {
margin:0;
}
</style>
<div class="toggleable closed">
<a href="#" onclick="return toggleDiv(this)">
<img src="/assets/images/triangle-closed.png" class="toggle-img" />
<strong>Example ProgressDialog with a second thread</strong></a>
<div class="toggleme">
<p>This example uses a second thread to track the progress of a process (which actually just
counts up to 100). The thread sends a {@link android.os.Message} back to the main
Activity through a {@link android.os.Handler} each time progress is made. The main Activity then updates the
ProgressDialog.</p>
<pre>
package com.example.progressdialog;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class NotificationTest extends Activity {
static final int PROGRESS_DIALOG = 0;
Button button;
ProgressThread progressThread;
ProgressDialog progressDialog;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Setup the button that starts the progress dialog
button = (Button) findViewById(R.id.progressDialog);
button.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
showDialog(PROGRESS_DIALOG);
}
});
}
protected Dialog onCreateDialog(int id) {
switch(id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(NotificationTest.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
progressThread = new ProgressThread(handler);
progressThread.start();
return progressDialog;
default:
return null;
}
}
// Define the Handler that receives messages from the thread and update the progress
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
int total = msg.getData().getInt("total");
progressDialog.setProgress(total);
if (total >= 100){
dismissDialog(PROGRESS_DIALOG);
progressThread.setState(ProgressThread.STATE_DONE);
}
}
};
/** Nested class that performs progress calculations (counting) */
private class ProgressThread extends Thread {
Handler mHandler;
final static int STATE_DONE = 0;
final static int STATE_RUNNING = 1;
int mState;
int total;
ProgressThread(Handler h) {
mHandler = h;
}
public void run() {
mState = STATE_RUNNING;
total = 0;
while (mState == STATE_RUNNING) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Log.e("ERROR", "Thread Interrupted");
}
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", total);
msg.setData(b);
mHandler.sendMessage(msg);
total++;
}
}
/* sets the current state for the thread,
* used to stop the thread */
public void setState(int state) {
mState = state;
}
}
}
</pre>
</div> <!-- end toggleme -->
</div> <!-- end toggleable -->
<h2 id="CustomDialog">Creating a Custom Dialog</h2>
<img src="{@docRoot}images/dialog_custom.png" alt="" style="float:right" />
<p>If you want a customized design for a dialog, you can create your own layout
for the dialog window with layout and widget elements.
After you've defined your layout, pass the root View object or
layout resource ID to {@link android.app.Dialog#setContentView(View)}.</p>
<p>For example, to create the dialog shown to the right:</p>
<ol>
<li>Create an XML layout saved as <code>custom_dialog.xml</code>:
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
>
&lt;ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#FFF"
/>
&lt;/LinearLayout>
</pre>
<p>This XML defines an {@link android.widget.ImageView} and a {@link android.widget.TextView}
inside a {@link android.widget.LinearLayout}.</p>
<li>Set the above layout as the dialog's content view and define the content
for the ImageView and TextView elements:</p>
<pre>
Context mContext = getApplicationContext();
Dialog dialog = new Dialog(mContext);
dialog.setContentView(R.layout.custom_dialog);
dialog.setTitle("Custom Dialog");
TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
</pre>
<p>After you instantiate the Dialog, set your custom layout as the dialog's content view with
{@link android.app.Dialog#setContentView(int)}, passing it the layout resource ID.
Now that the Dialog has a defined layout, you can capture View objects from the layout with
{@link android.app.Dialog#findViewById(int)} and modify their content.</p>
</li>
<li>That's it. You can now show the dialog as described in
<a href="#ShowingADialog">Showing A Dialog</a>.</li>
</ol>
<p>A dialog made with the base Dialog class must have a title. If you don't call
{@link android.app.Dialog#setTitle(CharSequence) setTitle()}, then the space used for the title
remains empty, but still visible. If you don't want
a title at all, then you should create your custom dialog using the
{@link android.app.AlertDialog} class. However, because an AlertDialog is created easiest with
the {@link android.app.AlertDialog.Builder} class, you do not have access to the
{@link android.app.Dialog#setContentView(int)} method used above. Instead, you must use
{@link android.app.AlertDialog.Builder#setView(View)}. This method accepts a {@link android.view.View} object,
so you need to inflate the layout's root View object from
XML.</p>
<p>To inflate the XML layout, retrieve the {@link android.view.LayoutInflater} with
{@link android.app.Activity#getLayoutInflater()}
(or {@link android.content.Context#getSystemService(String) getSystemService()}),
and then call
{@link android.view.LayoutInflater#inflate(int, ViewGroup)}, where the first parameter
is the layout resource ID and the second is the ID of the root View. At this point, you can use
the inflated layout to find View objects in the layout and define the content for the
ImageView and TextView elements. Then instantiate the AlertDialog.Builder and set the
inflated layout for the dialog with {@link android.app.AlertDialog.Builder#setView(View)}.</p>
<p>Here's an example, creating a custom layout in an AlertDialog:</p>
<pre>
AlertDialog.Builder builder;
AlertDialog alertDialog;
Context mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog,
(ViewGroup) findViewById(R.id.layout_root));
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
builder = new AlertDialog.Builder(mContext);
builder.setView(layout);
alertDialog = builder.create();
</pre>
<p>Using an AlertDialog for your custom layout lets you
take advantage of built-in AlertDialog features like managed buttons,
selectable lists, a title, an icon and so on.</p>
<p>For more information, refer to the reference documentation for the
{@link android.app.Dialog} and {@link android.app.AlertDialog.Builder}
classes.</p>

View File

@ -0,0 +1,98 @@
page.title=How Android Draws Views
parent.title=User Interface
parent.link=index.html
@jd:body
<p>When an Activity receives focus, it will be requested to draw its layout.
The Android framework will handle the procedure for drawing, but the Activity must provide
the root node of its layout hierarchy.</p>
<p>Drawing begins with the root node of the layout. It is requested to measure and
draw the layout tree. Drawing is handled by walking the tree and rendering each View that
intersects the invalid region. In turn, each View group is responsible for requesting
each of its children to be drawn (with the <code>{@link android.view.View#draw(Canvas) draw()}</code> method)
and each View is responsible for drawing itself.
Because the tree is traversed in-order,
this means that parents will be drawn before (i.e., behind) their children, with
siblings drawn in the order they appear in the tree.
</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p>The framework will not draw Views that are not in the invalid region, and also
will take care of drawing the Views background for you.</p>
<p>You can force a View to draw, by calling <code>{@link android.view.View#invalidate()}</code>.
</p>
</div>
</div>
<p>
Drawing the layout is a two pass process: a measure pass and a layout pass. The measuring
pass is implemented in <code>{@link android.view.View#measure(int, int)}</code> and is a top-down traversal
of the View tree. Each View pushes dimension specifications down the tree
during the recursion. At the end of the measure pass, every View has stored
its measurements. The second pass happens in
<code>{@link android.view.View#layout(int,int,int,int)}</code> and is also top-down. During
this pass each parent is responsible for positioning all of its children
using the sizes computed in the measure pass.
</p>
<p>
When a View's <code>measure()</code> method returns, its <code>{@link android.view.View#getMeasuredWidth()}</code> and
<code>{@link android.view.View#getMeasuredHeight()}</code> values must be set, along with those for all of
that View's descendants. A View's measured width and measured height values
must respect the constraints imposed by the View's parents. This guarantees
that at the end of the measure pass, all parents accept all of their
children's measurements. A parent View may call <code>measure()</code> more than once on
its children. For example, the parent may measure each child once with
unspecified dimensions to find out how big they want to be, then call
<code>measure()</code> on them again with actual numbers if the sum of all the children's
unconstrained sizes is too big or too small (i.e., if the children don't agree among themselves
as to how much space they each get, the parent will intervene and set the rules on the second pass).
</p>
<div class="sidebox-wrapper">
<div class="sidebox"><p>
To initiate a layout, call <code>{@link android.view.View#requestLayout}</code>. This method is typically
called by a View on itself when it believes that is can no longer fit within
its current bounds.</p>
</div>
</div>
<p>
The measure pass uses two classes to communicate dimensions. The
{@link android.view.View.MeasureSpec} class is used by Views to tell their parents how they
want to be measured and positioned. The base LayoutParams class just
describes how big the View wants to be for both width and height. For each
dimension, it can specify one of:</p>
<ul>
<li> an exact number
<li><var>FILL_PARENT</var>, which means the View wants to be as big as its parent
(minus padding)</li>
<li><var>WRAP_CONTENT</var>, which means that the View wants to be just big enough to
enclose its content (plus padding).</li>
</ul>
<p>There are subclasses of LayoutParams for different subclasses of ViewGroup.
For example, RelativeLayout has its own subclass of LayoutParams, which includes
the ability to center child Views horizontally and vertically.
</p>
<p>
MeasureSpecs are used to push requirements down the tree from parent to
child. A MeasureSpec can be in one of three modes:</p>
<ul>
<li><var>UNSPECIFIED</var>: This is used by a parent to determine the desired dimension
of a child View. For example, a LinearLayout may call <code>measure()</code> on its child
with the height set to <var>UNSPECIFIED</var> and a width of <var>EXACTLY</var> 240 to find out how
tall the child View wants to be given a width of 240 pixels.</li>
<li><var>EXACTLY</var>: This is used by the parent to impose an exact size on the
child. The child must use this size, and guarantee that all of its
descendants will fit within this size.</li>
<li><var>AT_MOST</var>: This is used by the parent to impose a maximum size on the
child. The child must guarantee that it and all of its descendants will fit
within this size.</li>
</ul>

View File

@ -0,0 +1,235 @@
page.title=User Interface
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#ViewHierarchy">View Hierarchy</a></li>
<li><a href="#Layout">Layout</a></li>
<li><a href="#Widgets">Widgets</a></li>
<li><a href="#Events">UI Events</a></li>
<li><a href="#Menus">Menus</a></li>
<li><a href="#Advanced">Advanced Topics</a>
<ol>
<li><a href="#Adapters">Adapters</a></li>
<li><a href="#StylesAndThemes">Styles and Themes</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
<li>{@link android.widget Widget classes}</li>
</ol>
</div>
</div>
<p>In an Android application, the user interface is built using {@link android.view.View} and
{@link android.view.ViewGroup} objects. There are many types of views and view groups, each of which
is a descendant of the {@link android.view.View} class.</p>
<p>View objects are the basic units of user interface expression on the Android platform.
The View class serves as the base for subclasses called "widgets," which offer fully implemented
UI objects, like text fields and buttons. The ViewGroup class serves as the base for subclasses called "layouts,"
which offer different kinds of layout architecture, like linear, tabular and relative.</p>
<p>A View object is a data structure whose properties store the layout parameters and content for a specific
rectangular area of the screen. A View object handles its own measurement, layout, drawing, focus change,
scrolling, and key/gesture interactions for the rectangular area of the screen in which it resides. As an
object in the user interface, a View is also a point of interaction for the user and the receiver
of the interaction events.</p>
<h2 id="ViewHierarchy">View Hierarchy</h2>
<p>On the Android platform, you define an Activity's UI using a hierarchy of View and ViewGroup nodes,
as shown in the diagram below. This hierarchy tree can be as simple or complex as you need it to be, and you
can build it up using Android's set of predefined widgets and layouts, or with custom Views that you
create yourself.</p>
<img src="{@docRoot}images/viewgroup.png" alt="" width="312" height="211" align="center"/>
<p>
In order to attach the view hierarchy tree to the screen for rendering, your Activity must call the
<code>{@link android.app.Activity#setContentView(int) setContentView()}</code>
method and pass a reference to the root node object. The Android system
receives this reference and uses it to invalidate, measure, and draw the tree. The root node of the hierarchy requests
that its child nodes draw themselves &mdash; in turn, each view group node is responsible for calling
upon each of its own child views to draw themselves.
The children may request a size and location within the parent, but the parent object has the final
decision on where how big each child can be. Android parses
the elements of your layout in-order (from the top of the hierarchy tree), instantiating the Views and
adding them to their parent(s). Because these are drawn in-order, if there are elements that
overlap positions, the last one to be drawn will lie on top of others previously drawn to that space.</p>
<p>For a more detailed discussion on how view hierarchies are measured
and drawn, read <a href="how-android-draws.html">How Android Draws Views</a>.</p>
<h2 id="Layout">Layout</h2>
<p>The most common way to define your layout and express the view hierarchy is with an XML layout file.
XML offers a human-readable structure for the layout, much like HTML. Each element in XML is
either a View or ViewGroup object (or descendant thereof). View objects are leaves in the tree,
ViewGroup objects are branches in the tree (see the View Hierarchy figure above).</p>
<p>The name of an XML element
is respective to the Java class that it represents. So a <code>&lt;TextView></code> element creates
a {@link android.widget.TextView} in your UI, and a <code>&lt;LinearLayout></code> element creates
a {@link android.widget.LinearLayout} view group. When you load a layout resource,
the Android system initializes these run-time objects, corresponding to the elements in your layout.</p>
<p>For example, a simple vertical layout with a text view and a button looks like this:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
&lt;Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
&lt;/LinearLayout>
</pre>
<p>Notice that the LinearLayout element contains both the TextView and the Button. You can nest
another LinearLayout (or other type of view group) inside here, to lengthen the view hierarchy and create a more
complex layout.</p>
<p>For more on building a UI layout, read <a href="declaring-layout.html">Declaring Layout</a>.
<div class="sidebox-wrapper">
<div class="sidebox">
<p><b>Tip:</b> You can also draw View and ViewGroups objects in Java code,
using the <code>{@link android.view.ViewGroup#addView(View)}</code> methods
to dynamically insert new View and ViewGroup objects.</p>
</div>
</div>
<p>There are a variety of ways in which you can layout your views. Using more and different kinds of view groups,
you can structure child views and view groups in an infinite number of ways.
Some pre-defined view groups offered by Android (called layouts) include LinearLayout, RelativeLayout,
TableLayout, GridLayout and others. Each offers a unique set of layout parameters that are used to define the
positions of child views and layout structure.</p>
<p>To learn about some of the different kinds of view groups used for a layout,
read <a href="layout-objects.html">Common Layout Objects</a>.</p>
<h2 id="Widgets">Widgets</h2>
<p>A widget is a View object that serves as an interface for interaction with the user.
Android provides a set of fully implemented
widgets, like buttons, checkboxes, and text-entry fields, so you can quickly build your UI.
Some widgets provided by Android are more complex, like a date picker, a clock, and zoom controls.
But you're not limited to the kinds of widgets provided by the Android platform. If you'd
like to do something more customized and create your own actionable elements, you can, by defining your own
View object or by extending and combining existing widgets.</p>
<p>Read more in <a href="custom-components.html">Building Custom Components</a>.</p>
<p>For a list of the widgets provided by Android, see the {@link android.widget} package.</p>
<h2 id="Events">UI Events</h2>
<p>Once you've added some Views/widgets to the UI, you probably want to know about the
user's interaction with them, so you can perform actions. To be informed of UI events, you need to
do one of two things:</p>
<ul>
<li><strong>Define an event listener and register it with the View.</strong> More often than not,
this is how you'll listen for events. The View class contains a collection of nested interfaces named
On<em>&lt;something></em>Listener, each with a callback method called <code>On<em>&lt;something></em>()</code>.
For example, {@link android.view.View.OnClickListener} (for handling "clicks" on a View),
{@link android.view.View.OnTouchListener} (for handling touch screen events in a View), and
{@link android.view.View.OnKeyListener} (for handling device key presses within a View). So if you want your View
to be notified when it is "clicked" (such as when a button is selected), implement OnClickListener and define
its <code>onClick()</code> callback method (where you perform the action upon click), and register it
to the View with <code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>.
</li>
<li><strong>Override an existing callback method for the View.</strong> This is
what you should do when you've implemented your own View class and want to listen for specific events
that occur within it. Example events you can handle include when the
screen is touched (<code>{@link android.view.View#onTouchEvent(MotionEvent) onTouchEvent()}</code>), when
the trackball is moved (<code>{@link android.view.View#onTrackballEvent(MotionEvent) onTrackballEvent()}</code>),
or when a key on the device is pressed (<code>{@link android.view.View#onKeyDown(int, KeyEvent)
onKeyDown()}</code>). This allows you to define the default behavior for each event inside your custom View and determine
whether the event should be passed on to some other child View. Again, these are callbacks to the View class,
so your only chance to define them is when you
<a href="{@docRoot}guide/topics/ui/custom-components.html">build a custom component</a>.
</li>
</ul>
<p>Continue reading about handling user interaction with Views in the <a href="ui-events.html">Handling UI Events</a>
document.</p>
<h2 id="Menus">Menus</h2>
<p>Application menus are another important part of an application's UI. Menus offers a reliable interface that reveals
application functions and settings. The most common application menu is revealed by pressing
the MENU key on the device. However, you can also add Context Menus, which may be revealed when the user presses
and holds down on an item.</p>
<p>Menus are also structured using a View hierarchy, but you don't define this structure yourself. Instead,
you define the <code>{@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()}</code> or
<code>{@link android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenu.ContextMenuInfo) onCreateContextMenu()}</code>
callback methods for your Activity and declare the items that you want to include in your menu.
At the appropriate time, Android will automatically create the necessary View hierarchy for the menu and
draw each of your menu items in it.</p>
<p>Menus also handle their own events, so there's no need to register event listeners on the items in your menu.
When an item in your menu is selected, the <code>{@link android.app.Activity#onOptionsItemSelected(MenuItem)
onOptionsItemSelected()}</code> or
<code>{@link android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}</code>
method will be called by the framework.</p>
<p>And just like your application layout, you have the option to declare the items for you menu in an XML file.</p>
<p>Read <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a> to learn more.</p>
<h2 id="Advanced">Advanced Topics</h2>
<p>Once you've grappled the fundamentals of creating a user interface, you can explore
some advanced features for creating a more complex application interface.</p>
<h3 id="Adapters">Adapters</h3>
<p>Sometimes you'll want to populate a view group with some information that can't be hard-coded, instead,
you want to bind your view to an external source of data. To do this, you use an AdapterView as
your view group and each child View is initialized and populated with data from the Adapter.</p>
<p>The AdapterView object is an implementation of ViewGroup that determines its child views
based on a given Adapter object. The Adapter acts like a courier between your data source (perhaps an
array of external strings) and the AdapterView, which displays it. There are several implementations
of the Adapter class, for specific tasks, such as the CursorAdapter for reading database data from a Cursor,
or an ArrayAdapter for reading from an arbitrary array.</p>
<p>To learn more about using an Adapter to populate your views, read
<a href="binding.html">Binding to Data with AdapterView</a>.</p>
<h3 id="StylesAndThemes">Styles and Themes</h3>
<p>Perhaps you're not satisfied with the look of the standard widgets. To revise them, you can create some
of your own styles and themes.</p>
<ul>
<li>A style is a set of one or more formatting attributes that you can apply as a unit to individual elements
in your layout. For example, you could define a style that specifies a certain text size and color, then
apply it to only specific View elements.</li>
<li>A theme is a set of one or more formatting attributes that you can apply as a unit to all activities in
an application, or just a single activity. For example, you could define a theme that sets specific colors for
the window frame and the panel background, and sets text sizes and colors for menus. This theme can then be
applied to specific activities or the entire application.</li>
</ul>
<p>Styles and themes are resources. Android provides some default style and theme resources that you can use,
or you can declare your own custom style and theme resources.</p>
<p>Learn more about using styles and themes in the
<a href="themes.html">Applying Styles and Themes</a> document.</p>

View File

@ -0,0 +1,291 @@
page.title=Common Layout Objects
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#framelayout">FrameLayout</a></li>
<li><a href="#linearlayout">LinearLayout</a></li>
<li><a href="#tablelayout">TableLayout</a></li>
<li><a href="#relativelayout">RelativeLayout</a></li>
<li><a href="#viewgroupsummary">Summary of Important View Groups</a></li>
</ol>
</div>
</div>
<p>This section describes some of the more common types of layout objects
to use in your applications. Like all layouts, they are subclasses of {@link android.view.ViewGroup ViewGroup}.</p>
<p>Also see the <a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a> tutorials for
some guidance on using more Android View layouts.</p>
<h2 id="framelayout">FrameLayout</h2>
<p>{@link android.widget.FrameLayout FrameLayout} is the simplest type of layout
object. It's basically a blank space on your screen that you can
later fill with a single object &mdash; for example, a picture that you'll swap in and out.
All child elements of the FrameLayout are pinned to the top left corner of the screen; you cannot
specify a different location for a child view. Subsequent child views will simply be drawn over previous ones,
partially or totally obscuring them (unless the newer object is transparent).
</p>
<h2 id="linearlayout">LinearLayout</h2>
<p>{@link android.widget.LinearLayout LinearLayout} aligns all children in a
single direction &mdash; vertically or horizontally, depending on how you
define the <code>orientation</code> attribute. All children 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 {@link
android.widget.LinearLayout LinearLayout} respects <em>margin</em>s between children
and the <em>gravity</em> (right, center, or left alignment) of each child. </p>
<p>{@link android.widget.LinearLayout LinearLayout} also supports assigning a
<em>weight</em> to individual children. This attribute assigns an "importance" value to a view,
and allows it to expand to fill any remaining space in the parent view.
Child views can specify an integer 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. For example, if there are three text boxes and two of
them declare a weight of 1, while the other is given no weight (0), the third text box 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 boxes are measured.
If the third box 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.</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<p><strong>Tip</strong>: To create a proportionate size
layout on the screen, create a container view group object with the
<code>layout_width</code> and <code>layout_height</code> attributes set to <var>fill_parent</var>; assign
the children <code>height</code> or <code>width</code> to <code>0</code> (zero); then assign relative
<code>weight</code> values
to each child, depending on what proportion of the screen each should
have.</p>
</div>
</div>
<p>The following two forms represent a {@link android.widget.LinearLayout LinearLayout} with a set of elements: a
button, some labels and text boxes. The text boxes have their width set to <var>fill_parent</var>; other
elements are set to <var>wrap_content</var>. The gravity, by default, is left.
The difference between the two versions of the form is that the form
on the left has weight values unset (0 by default), while the form on the right has
the comments text box weight set to 1. If the Name textbox had also been set
to 1, the Name and Comments text boxes would be the same height. </p>
<img src="{@docRoot}images/linearlayout.png" alt="" />
<p>Within a horizontal {@link android.widget.LinearLayout LinearLayout}, items are aligned by the position of
their text base line (the first line of the first list element &mdash; topmost or
leftmost &mdash; is considered the reference line). This is so that people scanning
elements in a form shouldn't have to jump up and down to read element text in
neighboring elements. This can be turned off by setting
<code>android:baselineAligned=&quot;false&quot;</code> in the layout XML. </p>
<p>To view other sample code, see the
<a href="{@docRoot}resources/tutorials/views/hello-linearlayout.html">Hello LinearLayout</a> tutorial.</p>
<h2 id="tablelayout">TableLayout</h2>
<p>{@link android.widget.TableLayout} positions its children into rows
and columns. TableLayout containers do not display border lines for their rows, columns,
or cells. The table will have as many columns as the row with the most cells. A table can leave
cells empty, but cells cannot span columns, as they can in HTML.</p>
<p>{@link android.widget.TableRow} objects are the child views of a TableLayout
(each TableRow defines a single row in the table).
Each row has zero or more cells, each of which is defined by any kind of other View. So, the cells of a row may be
composed of a variety of View objects, like ImageView or TextView objects.
A cell may also be a ViewGroup object (for example, you can nest another TableLayout as a cell).</p>
<p>The following sample layout has two rows and two cells in each. The accompanying screenshot shows the
result, with cell borders displayed as dotted lines (added for visual effect). </p>
<table class="columns">
<tr>
<td>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1">
&lt;TableRow>
&lt;TextView
android:text="@string/table_layout_4_open"
android:padding="3dip" />
&lt;TextView
android:text="@string/table_layout_4_open_shortcut"
android:gravity="right"
android:padding="3dip" />
&lt;/TableRow>
&lt;TableRow>
&lt;TextView
android:text="@string/table_layout_4_save"
android:padding="3dip" />
&lt;TextView
android:text="@string/table_layout_4_save_shortcut"
android:gravity="right"
android:padding="3dip" />
&lt;/TableRow>
&lt;/TableLayout>
</pre></td>
<td><img src="{@docRoot}images/table_layout.png" alt="" style="margin:0" /></td>
</tr>
</table>
<p>Columns can be hidden, marked to stretch and fill the available screen space,
or can be marked as shrinkable to force the column to shrink until the table
fits the screen. See the {@link android.widget.TableLayout TableLayout reference}
documentation for more details. </p>
<p>To view sample code, see the <a href="{@docRoot}resources/tutorials/views/hello-tablelayout.html">Hello
TableLayout</a> tutorial.</p>
<h2 id="relativelayout">RelativeLayout</h2>
<p>{@link android.widget.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. Elements are rendered in the order given, so if the first element
is centered in the screen, other elements aligning themselves to that element
will be aligned relative to screen center. Also, because of this ordering, if using XML to specify this layout,
the element that you will reference (in order to position other view objects) must be listed in the XML
file before you refer to it from the other views via its reference ID. </p>
<p>The example below shows an XML file and the resulting screen in the UI.
Note that the attributes that refer to relative elements (e.g., <var>layout_toLeft</var>)
refer to the ID using the syntax of a relative resource
(<var>@id/<em>id</em></var>). </p>
<table class="columns">
<tr>
<td>
<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:background=&quot;@drawable/blue&quot;
android:padding=&quot;10px&quot; &gt;
&lt;TextView android:id=&quot;@+id/label&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:text=&quot;Type here:&quot; /&gt;
&lt;EditText android:id=&quot;@+id/entry&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;wrap_content&quot;
android:background=&quot;@android:drawable/editbox_background&quot;
android:layout_below=&quot;@id/label&quot; /&gt;
&lt;Button android:id=&quot;@+id/ok&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_below=&quot;@id/entry&quot;
android:layout_alignParentRight=&quot;true&quot;
android:layout_marginLeft=&quot;10px&quot;
android:text=&quot;OK&quot; /&gt;
&lt;Button android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_toLeftOf=&quot;@id/ok&quot;
android:layout_alignTop=&quot;@id/ok&quot;
android:text=&quot;Cancel&quot; /&gt;
&lt;/RelativeLayout&gt;
</pre></td>
<td><img src="{@docRoot}images/designing_ui_layout_example.png" alt="" style="margin:0" /></td>
</tr>
</table>
<p>Some of these properties are supported directly by
the element, and some are supported by its LayoutParams member (subclass RelativeLayout
for all the elements in this screen, because all elements are children of a RelativeLayout
parent object). The defined RelativeLayout parameters are: <code>width</code>, <code>height</code>,
<code>below</code>, <code>alignTop</code>, <code>toLeft</code>, <code>padding[Bottom|Left|Right|Top]</code>,
and <code>margin[Bottom|Left|Right|Top]</code>. Note that some of these parameters specifically support
relative layout positions &mdash; their values must be the ID of the element to which you'd like this view laid relative.
For example, assigning the parameter <code>toLeft="my_button"</code> to a TextView would place the TextView to
the left of the View with the ID <var>my_button</var> (which must be written in the XML <em>before</em> the TextView). </p>
<p>To view this sample code, see the <a href="{@docRoot}resources/tutorials/views/hello-relativelayout.html">Hello
RelativeLayout</a> tutorial.</p>
<h2 id="viewgroupsummary">Summary of Important View Groups</h2>
<p>These objects all hold child UI elements. Some provide their own form of a visible UI, while others
are invisible structures that only manage the layout of their child views. </p>
<table width="100%" border="1">
<tr>
<th scope="col">Class</th>
<th scope="col">Description</th>
</tr>
<tr>
<td>{@link android.widget.FrameLayout FrameLayout}</td>
<td>Layout that acts as a view frame to display
a single object. </td>
</tr>
<tr>
<td>{@link android.widget.Gallery Gallery} </td>
<td>A horizontal scrolling display of images, from a bound list. </td>
</tr>
<tr>
<td>{@link android.widget.GridView GridView} </td>
<td>Displays a scrolling grid of m columns and n rows.</td>
</tr>
<tr>
<td>{@link android.widget.LinearLayout LinearLayout} </td>
<td>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. </td>
</tr>
<tr>
<td>{@link android.widget.ListView ListView} </td>
<td>Displays a scrolling single column list. </td>
</tr>
<tr>
<td>{@link android.widget.RelativeLayout RelativeLayout} </td>
<td>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). </td>
</tr>
<tr>
<td>{@link android.widget.ScrollView ScrollView} </td>
<td>A vertically scrolling column of elements. </td>
</tr>
<tr>
<td>{@link android.widget.Spinner Spinner} </td>
<td>Displays a single item at a time from a bound list, inside a one-row
textbox. Rather like a one-row listbox that can scroll either horizontally
or vertically. </td>
</tr>
<tr>
<td>{@link android.view.SurfaceView SurfaceView} </td>
<td>Provides direct access to a dedicated drawing surface. It can hold child
views layered on top of the surface, but is intended for applications
that need to draw pixels, rather than using widgets. </td>
</tr>
<tr>
<td>{@link android.widget.TabHost TabHost} </td>
<td>Provides a tab selection list that monitors clicks and enables the application
to change the screen whenever a tab is clicked. </td>
</tr>
<tr>
<td>{@link android.widget.TableLayout TableLayout} </td>
<td>A tabular layout with an arbitrary number of rows and columns, each cell
holding the widget of your choice. The rows resize to fit the largest
column. The cell borders are not
visible. </td>
</tr>
<tr>
<td>{@link android.widget.ViewFlipper ViewFlipper} </td>
<td>A list that displays one item at a time, inside a one-row textbox. It
can be set to swap items at timed intervals, like a slide show. </td>
</tr>
<tr>
<td>{@link android.widget.ViewSwitcher ViewSwitcher} </td>
<td>Same as ViewFlipper. </td>
</tr>
</table>

View File

@ -0,0 +1,650 @@
page.title=Creating Menus
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#xml">Defining Menus</a></li>
<li><a href="#Inflating">Inflating a Menu Resource</a>
<li><a href="#options-menu">Creating an Options Menu</a>
<ol>
<li><a href="#ChangingTheMenu">Changing the menu when it opens</a></li>
</ol>
</li>
<li><a href="#context-menu">Creating a Context Menu</a></li>
<li><a href="#submenu">Creating a Submenu</a></li>
<li><a href="#features">Other Menu Features</a>
<ol>
<li><a href="#groups">Menu groups</a></li>
<li><a href="#checkable">Checkable menu items</a></li>
<li><a href="#shortcuts">Shortcut keys</a></li>
<li><a href="#intents">Intents for menu items</a></li>
</ol>
</li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.view.Menu}</li>
<li>{@link android.view.MenuItem}</li>
<li>{@link android.view.ContextMenu}</li>
<li>{@link android.view.SubMenu}</li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a></li>
</ol>
</div>
</div>
<p>Menus are an important part of an application that provide a familiar interface for the user
to access application functions and settings. Android offers an easy programming interface
for you to provide application menus in your application.</p>
<p>Android provides three types of application menus:</p>
<dl>
<dt><strong>Options Menu</strong></dt>
<dd>The primary menu for an Activity, which appears when the user presses
the device MENU key. Within the Options Menu are two groups:
<dl style="margin-top:1em">
<dt><em>Icon Menu</em></dt>
<dd>The menu items visible at the bottom of the screen
at the press of the MENU key. It supports a maximum of six menu items.
These are the only menu items that support icons and the only menu items that <em>do not</em> support
checkboxes or radio buttons.</dd>
<dt><em>Expanded Menu</em></dt>
<dd>The vertical list of menu items exposed by the "More" menu item in the Icon Menu.
When the Icon Menu is full, the expanded menu is comprised of the sixth
menu item and the rest.</dd>
</dl>
</dd>
<dt><strong>Context Menu</strong></dt>
<dd>A floating list of menu items that appears when the user performs a long-press on a View.
</dd>
<dt><strong>Submenu</strong></dt>
<dd>A floating list of menu items that the user opens by pressing a menu item in the Options
Menu or a context menu. A submenu item cannot support a nested submenu. </dd>
</dl>
<h2 id="xml">Defining Menus</h2>
<p>Instead of instantiating {@link android.view.Menu} objects in your application code, you should
define a menu and all its items in an XML <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>, then inflate the menu
resource (load it as a programmable object) in your application code. Defining your menus in XML is
a good practice because it separates your interface design from your application code (the same as
when you <a href="{@docRoot}guide/topics/ui/declaring-layout.html">define your Activity
layout</a>).</p>
<p>To define a menu, create an XML file inside your project's <code>res/menu/</code>
directory and build the menu with the following elements:</p>
<dl>
<dt><code>&lt;menu></code></dt>
<dd>Creates a {@link android.view.Menu}, which is a container for menu items. It must be
the root node and holds one or more of the following elements. You can also nest this element
in an {@code &lt;item&gt;} to create a submenu.</dd>
<dt><code>&lt;item></code></dt>
<dd>Creates a {@link android.view.MenuItem}, which represents a single item in a menu.</dd>
<dt><code>&lt;group></code></dt>
<dd>An optional, invisible container for {@code &lt;item&gt;} elements. It allows you to
categorize menu items so they share properties such as active state and visibility. See <a
href="#groups">Menu groups</a>.</dd>
</dl>
<p>For example, here is a file in <code>res/menu/</code> named <code>game_menu.xml</code>:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;item android:id="@+id/new_game"
android:icon="@drawable/ic_new_game"
android:title="@string/new_game" /&gt;
&lt;item android:id="@+id/quit"
android:icon="@drawable/ic_quit"
android:title="@string/quit" /&gt;
&lt;/menu&gt;
</pre>
<p>This example defines a menu with two menu items. Each item includes the attributes:</p>
<dl>
<dt>{@code android:id}</dt>
<dd>A resource ID that's unique to the item so that the application can recognize the item when
the user selects it.</dd>
<dt>{@code android:icon}</dt>
<dd>A drawable resource that is the icon visible to the user.</dd>
<dt>{@code android:title}</dt>
<dd>A string resource that is the title visible to the user.</dd>
</dl>
<p>For more about the XML syntax and attributes for a menu resource, see the <a
href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a> reference.</p>
<h2 id="Inflating">Inflating a Menu Resource</h2>
<p>You can inflate your menu resource (convert the XML resource into a programmable object) using
{@link android.view.MenuInflater#inflate(int,Menu) MenuInflater.inflate()}. For
example, the following code inflates the <code>game_menu.xml</code> file defined above during the
{@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} callback method, to be
used for the Options Menu:</p>
<pre>
&#64;Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
</pre>
<p>The {@link android.app.Activity#getMenuInflater()} method returns a {@link
android.view.MenuInflater} for the Activity. With this object, you can call {@link
android.view.MenuInflater#inflate(int,Menu) inflate()}, which inflates a menu resource into a
{@link android.view.Menu} object. In this example, the menu resource defined by
<code>game_menu.xml</code>
is inflated into the {@link android.view.Menu} that was passed into {@link
android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()}. (This callback method for
creating an option menu is discussed more in the next section.)</p>
<h2 id="options-menu">Creating an Options Menu</h2>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/options_menu.png" height="300" alt="" />
<p class="img-caption"><strong>Figure 1.</strong> Screenshot of an Options Menu.</p>
</div>
<p>The Options Menu is where you should include basic application functions
and necessary navigation items (for example, a button
to open application settings). The user
can open the Options Menu with the device MENU key.
Figure 1 shows a screenshot of an Options Menu.</p>
<p>When opened, the first visible portion of the Options Menu is called the Icon Menu. It
holds the first six menu items.
If you add more than six items to the Options Menu, Android places the sixth item and those after it
into the Expanded Menu, which the user can open with the "More" menu item.</p>
<p>When the user opens the Options Menu for the first time, Android calls your Activity's
{@link android.app.Activity#onCreateOptionsMenu(Menu)
onCreateOptionsMenu()} method. Override this method in your Activity
and populate the {@link android.view.Menu} that is passed into the method. Populate the
{@link android.view.Menu} by inflating a menu resource as described in <a
href="#Inflating">Inflating a Menu Resource</a>. (You can
also populate the menu in code, using {@link android.view.Menu#add(int,int,int,int)
add()} to add menu items.)</p>
<p>When the user selects a menu item from the Options Menu, the system calls your Activity's
{@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}
method. This method passes the
{@link android.view.MenuItem} that the user selected. You can identify the menu item by calling
{@link android.view.MenuItem#getItemId()}, which returns the unique ID for the menu
item (defined by the {@code android:id} attribute in the menu resource or with an integer passed
to the {@link android.view.Menu#add(int,int,int,int) add()} method). You can match this ID
against known menu items and perform the appropriate action.</p>
<p>For example:</p>
<pre>
&#64;Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
newGame();
return true;
case R.id.quit:
quit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
</pre>
<p>In this example, {@link android.view.MenuItem#getItemId()} queries the ID for the selected menu
item and the switch statement compares the ID against the resource IDs that were assigned to menu
items in the XML resource. When a switch case successfully handles the item, it
returns "true" to indicate that the item selection was handled. Otherwise, the default statement
passes the menu item to the super class in
case it can handle the item selected. (If you've directly extended the {@link android.app.Activity}
class, then the super class returns "false", but it's a good practice to
pass unhandled menu items to the super class instead of directly returning "false".)</p>
<p class="note"><strong>Tip:</strong> If your application contains multiple activities and
some of them provide the same Options Menu, consider creating
an Activity that implements nothing except the {@link android.app.Activity#onCreateOptionsMenu(Menu)
onCreateOptionsMenu()} and {@link android.app.Activity#onOptionsItemSelected(MenuItem)
onOptionsItemSelected()} methods. Then extend this class for each Activity that should share the
same Options Menu. This way, you have to manage only one set of code for handling menu
actions and each decendent class inherits the menu behaviors.<br/><br/>
If you want to add menu items to one of your decendent activities,
override {@link android.app.Activity#onCreateOptionsMenu(Menu)
onCreateOptionsMenu()} in that Activity. Call {@code super.onCreateOptionsMenu(menu)} so the
original menu items are created, then add new menu items with {@link
android.view.Menu#add(int,int,int,int) menu.add()}. You can also override the super class's
behavior for individual menu items.</p>
<h3 id="ChangingTheMenu">Changing the menu when it opens</h3>
<p>The {@link android.app.Activity#onCreateOptionsMenu(Menu) onCreateOptionsMenu()} method is
called only the first time the Options Menu is opened. The system keeps and re-uses the {@link
android.view.Menu} you define in this method until your Activity is destroyed. If you want to change
the Options Menu each time it opens, you must override the
{@link android.app.Activity#onPrepareOptionsMenu(Menu) onPrepareOptionsMenu()} method. This passes
you the {@link android.view.Menu} object as it currently exists. This is useful if you'd like to
remove, add, disable, or enable menu items depending on the current state of your application.</p>
<p class="note"><strong>Note:</strong>
You should never change items in the Options Menu based on the {@link android.view.View} currently
in focus. When in touch mode (when the user is not using a trackball or d-pad), Views
cannot take focus, so you should never use focus as the basis for modifying
items in the Options Menu. If you want to provide menu items that are context-sensitive to a {@link
android.view.View}, use a <a href="#context-menu">Context Menu</a>.</p>
<h2 id="context-menu">Creating a Context Menu</h2>
<p>A context menu is conceptually similar to the menu displayed when the user performs a
"right-click" on a PC. You should use a context menu to provide the user access to
actions that pertain to a specific item in the user interface. On Android, a context menu is
displayed when the user performs a "long press" (press and hold) on an item.</p>
<p>You can create a context menu for any View, though context menus are most often used for items in
a {@link android.widget.ListView}. When the user performs a long-press on an item in a ListView and
the list is registered to provide a context menu, the list item signals to the user that a context
menu is available by animating its background color&mdash;it transitions from
orange to white before opening the context menu. (The Contacts application demonstrates this
feature.)</p>
<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Register a ListView</h3>
<p>If your Activity uses a {@link android.widget.ListView} and
you want all list items to provide a context menu, register all items for a context
menu by passing the {@link android.widget.ListView} to {@link
android.app.Activity#registerForContextMenu(View) registerForContextMenu()}. For
example, if you're using a {@link android.app.ListActivity}, register all list items like this:</p>
<p><code>registerForContextMenu({@link android.app.ListActivity#getListView()});</code></p>
</div>
</div>
<p>In order for a View to provide a context menu, you must "register" the view for a context
menu. Call {@link android.app.Activity#registerForContextMenu(View) registerForContextMenu()} and
pass it the {@link android.view.View} you want to give a context menu. When this View then
receives a long-press, it displays a context menu.</p>
<p>To define the context menu's appearance and behavior, override your Activity's context menu
callback methods, {@link android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
onCreateContextMenu()} and
{@link android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}.</p>
<p>For example, here's an {@link
android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
onCreateContextMenu()} that uses the {@code context_menu.xml} menu resource:</p>
<pre>
&#64;Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
</pre>
<p>{@link android.view.MenuInflater} is used to inflate the context menu from a <a
href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a>. (You can also use
{@link android.view.Menu#add(int,int,int,int) add()} to add menu items.) The callback method
parameters include the {@link android.view.View}
that the user selected and a {@link android.view.ContextMenu.ContextMenuInfo} object that provides
additional information about the item selected. You might use these parameters to determine
which context menu should be created, but in this example, all context menus for the Activity are
the same.</p>
<p>Then when the user selects an item from the context menu, the system calls {@link
android.app.Activity#onContextItemSelected(MenuItem) onContextItemSelected()}. Here is an example
of how you can handle selected items:</p>
<pre>
&#64;Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
editNote(info.id);
return true;
case R.id.delete:
deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
</pre>
<p>The structure of this code is similar to the example for <a href="#options-menu">Creating an
Options Menu</a>, in which {@link android.view.MenuItem#getItemId()} queries the ID for the selected
menu item and a switch statement matches the item to the IDs that are defined in the menu resource.
And like the options menu example, the default statement calls the super class in case it
can handle menu items not handled here, if necessary.</p>
<p>In this example, the selected item is an item from a {@link android.widget.ListView}. To
perform an action on the selected item, the application needs to know the list
ID for the selected item (it's position in the ListView). To get the ID, the application calls
{@link android.view.MenuItem#getMenuInfo()}, which returns a {@link
android.widget.AdapterView.AdapterContextMenuInfo} object that includes the list ID for the
selected item in the {@link android.widget.AdapterView.AdapterContextMenuInfo#id id} field. The
local methods <code>editNote()</code> and <code>deleteNote()</code> methods accept this list ID to
perform an action on the data specified by the list ID.</p>
<p class="note"><strong>Note:</strong> Items in a context menu do not support icons or shortcut
keys.</p>
<h2 id="submenu">Creating Submenus</h2>
<p>A submenu is a menu that the user can open by selecting an item in another menu. You can add a
submenu to any menu (except a submenu). Submenus are useful when your application has a lot of
functions that can be organized into topics, like items in a PC application's menu bar (File, Edit,
View, etc.).</p>
<p>When creating your <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu
resource</a>, you can create a submenu by adding a {@code &lt;menu&gt;} element as the child of an
{@code &lt;item&gt;}. For example:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;item android:id="@+id/file"
android:icon="@drawable/file"
android:title="@string/file" &gt;
&lt;!-- "file" submenu --&gt;
&lt;menu"&gt;
&lt;item android:id="@+id/new"
android:title="@string/new" /&gt;
&lt;item android:id="@+id/open"
android:title="@string/open" /&gt;
&lt;/menu&gt;
&lt;/item&gt;
&lt;/menu&gt;
</pre>
<p>When the user selects an item from a submenu, the parent menu's respective on-item-selected
callback method receives the event. For instance, if the above menu is applied as an Options Menu,
then the {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()} method
is called when a submenu item is selected.</p>
<p>You can also use {@link android.view.Menu#addSubMenu(int,int,int,int) addSubMenu()} to
dynamically add a {@link android.view.SubMenu} to an existing {@link android.view.Menu}. This
returns the new {@link android.view.SubMenu} object, to which you can add
submenu items, using {@link android.view.Menu#add(int,int,int,int) add()}</p>
<h2 id="features">Other Menu Features</h2>
<p>Here are some other features that you can apply to most menu items.</p>
<h3 id="groups">Menu groups</h3>
<p>A menu group is a collection of menu items that share certain traits. With a group, you
can:</p>
<ul>
<li>Show or hide all items with {@link android.view.Menu#setGroupVisible(int,boolean)
setGroupVisible()}</li>
<li>Enable or disable all items with {@link android.view.Menu#setGroupEnabled(int,boolean)
setGroupEnabled()}</li>
<li>Specify whether all items are checkable with {@link
android.view.Menu#setGroupCheckable(int,boolean,boolean) setGroupCheckable()}</li>
</ul>
<p>You can create a group by nesting {@code &lt;item&gt;} elements inside a {@code &lt;group&gt;}
element in your menu resource or by specifying a group ID with the the {@link
android.view.Menu#add(int,int,int,int) add()} method.</p>
<p>Here's an example menu resource that includes a group:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;item android:id="@+id/item1"
android:icon="@drawable/item1"
android:title="@string/item1" /&gt;
&lt;!-- menu group --&gt;
&lt;group android:id="@+id/group1"&gt;
&lt;item android:id="@+id/groupItem1"
android:title="@string/groupItem1" /&gt;
&lt;item android:id="@+id/groupItem2"
android:title="@string/groupItem2" /&gt;
&lt;/group&gt;
&lt;/menu&gt;
</pre>
<p>The items that are in the group appear the same as the first item that is not in a
group&mdash;all three items in the menu are siblings. However, you can modify the traits of the two
items in the group by referencing the group ID and using the methods listed above.</p>
<h3 id="checkable">Checkable menu items</h3>
<div class="figure" style="width:200px">
<img src="{@docRoot}images/radio_buttons.png" height="300" alt="" />
<p class="img-caption"><strong>Figure 2.</strong> Screenshot of checkable menu items</p>
</div>
<p>A menu can be useful as an interface for turning options on and off, using a checkbox for
stand-alone options, or radio buttons for groups of
mutually exclusive options. Figure 2 shows a submenu with items that are checkable with radio
buttons.</p>
<p class="note"><strong>Note:</strong> Menu items in the Icon Menu (from the Options Menu) cannot
display a checkbox or radio button. If you choose to make items in the Icon Menu checkable,
you must manually indicate the checked state by swapping the icon and/or text
each time the state changes.</p>
<p>You can define the checkable behavior for individual menu items using the {@code
android:checkable} attribute in the {@code &lt;item&gt;} element, or for an entire group with
the {@code android:checkableBehavior} attribute in the {@code &lt;group&gt;} element. For
example, all items in this menu group are checkable with a radio button:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;group android:checkableBehavior="single"&gt;
&lt;item android:id="@+id/red"
android:title="@string/red" /&gt;
&lt;item android:id="@+id/blue"
android:title="@string/blue" /&gt;
&lt;/group&gt;
&lt;/menu&gt;
</pre>
<p>The {@code android:checkableBehavior} attribute accepts either:
<dl>
<dt>{@code single}</dt>
<dd>Only one item from the group can be checked (radio buttons)</dd>
<dt>{@code all}</dt>
<dd>All items can be checked (checkboxes)</dd>
<dt>{@code none}</dt>
<dd>No items are checkable</dd>
</dl>
<p>You can apply a default checked state to an item using the {@code android:checked} attribute in
the {@code &lt;item&gt;} element and change it in code with the {@link
android.view.MenuItem#setChecked(boolean) setChecked()} method.</p>
<p>When a checkable item is selected, the system calls your respective item-selected callback method
(such as {@link android.app.Activity#onOptionsItemSelected(MenuItem) onOptionsItemSelected()}). It
is here that you must set the state of the checkbox, because a checkbox or radio button does not
change its state automatically. You can query the current state of the item (as it was before the
user selected it) with {@link android.view.MenuItem#isChecked()} and then set the checked state with
{@link android.view.MenuItem#setChecked(boolean) setChecked()}. For example:</p>
<pre>
&#64;Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.vibrate:
case R.id.dont_vibrate:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
</pre>
<p>If you don't set the checked state this way, then the visible state of the item (the checkbox or
radio button) will not
change when the user selects it. When you do set the state, the Activity preserves the checked state
of the item so that when the user opens the menu later, the checked state that you
set is visible.</p>
<p class="note"><strong>Note:</strong>
Checkable menu items are intended to be used only on a per-session basis and not saved after the
application is destroyed. If you have application settings that you would like to save for the user,
you should store the data using <a
href="{@docRoot}guide/topics/data/data-storage.html#pref">Shared Preferences</a>.</p>
<h3 id="shortcuts">Shortcut keys</h3>
<p>You can add quick-access shortcut keys using letters and/or numbers to menu items with the
{@code android:alphabeticShortcut} and {@code android:numericShortcut} attributes in the {@code
&lt;item&gt;} element. You can also use the methods {@link
android.view.MenuItem#setAlphabeticShortcut(char)} and {@link
android.view.MenuItem#setNumericShortcut(char)}. Shortcut keys are <em>not</em>
case sensitive.</p>
<p>For example, if you apply the "s" character as an alphabetic shortcut to a "save" menu item, then
when the menu is open (or while the user holds the MENU key) and the user presses the "s" key,
the "save" menu item is selected.</p>
<p>This shortcut key is displayed as a tip in the menu item, below the menu item name
(except for items in the Icon Menu, which are displayed only if the user holds the MENU
key).</p>
<p class="note"><strong>Note:</strong> Shortcut keys for menu items only work on devices with a
hardware keyboard. Shortcuts cannot be added to items in a Context Menu.</p>
<h3 id="intents">Intents for menu items</h3>
<p>Sometimes you'll want a menu item to launch an Activity using an Intent (whether it's an
Actvitity in your application or another application). When you know the Intent you want to use and
have a specific menu item that should initiate the Intent, you can execute the Intent with {@link
android.app.Activity#startActivity(Intent) startActivity()} during the appropriate on-item-selected
callback method (such as the {@link android.app.Activity#onOptionsItemSelected(MenuItem)
onOptionsItemSelected()} callback).</p>
<p>However, if you are not certain that the user's device
contains an application that handles the Intent, then adding a menu item that executes the
Intent can result in a non-functioning menu item, because the Intent might not resolve to an
Activity that accepts it. To solve this, Android lets you dynamically add menu items to your menu
when Android finds activities on the device that handle your Intent.</p>
<p>If you're not familiar with creating Intents, read the <a
href="/guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>.</p>
<h4>Dynamically adding Intents</h4>
<p>When you don't know if the user's device has an application that handles a specific Intent,
you can define the Intent and let Android search the device for activities that accept the Intent.
When it finds activies that handle the Intent, it adds a menu item for
each one to your menu and attaches the appropriate Intent to open the Activity when the user
selects it.</p>
<p>To add menu items based on available activities that accept an Intent:</p>
<ol>
<li>Define an
Intent with the category {@link android.content.Intent#CATEGORY_ALTERNATIVE} and/or
{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE}, plus any other requirements.</li>
<li>Call {@link
android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
Menu.addIntentOptions()}. Android then searches for any applications that can perform the Intent
and adds them to your menu.</li>
</ol>
<p>If there are no applications installed
that satisfy the Intent, then no menu items are added.</p>
<p class="note"><strong>Note:</strong>
{@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} is used to handle the currently
selected element on the screen. So, it should only be used when creating a Menu in {@link
android.app.Activity#onCreateContextMenu(ContextMenu,View,ContextMenuInfo)
onCreateContextMenu()}.</p>
<p>For example:</p>
<pre>
&#64;Override
public boolean onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
// Create an Intent that describes the requirements to fulfill, to be included
// in our menu. The offering app must include a category value of Intent.CATEGORY_ALTERNATIVE.
Intent intent = new Intent(null, dataUri);
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
// Search and populate the menu with acceptable offering applications.
menu.addIntentOptions(
R.id.intent_group, // Menu group to which new items will be added
0, // Unique item ID (none)
0, // Order for the items (none)
this.getComponentName(), // The current Activity name
null, // Specific items to place first (none)
intent, // Intent created above that describes our requirements
0, // Additional flags to control items (none)
null); // Array of MenuItems that correlate to specific items (none)
return true;
}</pre>
<p>For each Activity found that provides an Intent filter matching the Intent defined, a menu
item is added, using the value in the Intent filter's <code>android:label</code> as the
menu item title and the application icon as the menu item icon. The
{@link android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
addIntentOptions()} method returns the number of menu items added.</p>
<p class="note"><strong>Note:</strong> When you call {@link
android.view.Menu#addIntentOptions(int,int,int,ComponentName,Intent[],Intent,int,MenuItem[])
addIntentOptions()}, it overrides any and all menu items by the menu group specified in the first
argument.</p>
<h4>Allowing your Activity to be added to menus</h4>
<p>You can also offer the services of your Activity to other applications, so your
application can be included in the menu of others (reverse the roles described above).</p>
<p>To be included in other application menus, you need to define an Intent
filter as usual, but be sure to include the {@link android.content.Intent#CATEGORY_ALTERNATIVE}
and/or {@link android.content.Intent#CATEGORY_SELECTED_ALTERNATIVE} values for the Intent filter
category. For example:</p>
<pre>
&lt;intent-filter label="Resize Image">
...
&lt;category android:name="android.intent.category.ALTERNATIVE" />
&lt;category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
...
&lt;/intent-filter>
</pre>
<p>Read more about writing Intent filters in the
<a href="/guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> document.</p>
<p>For a sample application using this technique, see the
<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">Note
Pad</a> sample code.</p>

View File

@ -0,0 +1,101 @@
page.title=Notifying the User
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Topics</h2>
<ol>
<li><a href="toasts.html">Creating Toast Notifications</a></li>
<li><a href="notifications.html">Creating Status Bar Notifications</a></li>
<li><a href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a></li>
</ol>
</div>
</div>
<p>Several types of situations may arise that require you to notify the user
about an event that occurs in your application. Some events require the user to respond
and others do not. For example:</p>
<ul>
<li>When an event such as saving a file is complete, a small message
should appear to confirm that the save was successful.</li>
<li>If the application is running in the background and needs the user's attention,
the application should create a notification that allows the user to respond at
his or her convenience.</li>
<li>If the application is
performing work that the user must wait for (such as loading a file),
the application should show a hovering progress wheel or bar.</li>
</ul>
<p>Each of these notification tasks can be achieved using a different technique:</p>
<ul>
<li>A <a href="#Toast">Toast Notification</a>, for brief messages that come
from the background.</li>
<li>A <a href="#StatusBar">Status Bar Notification</a>, for persistent reminders
that come from the background and request the user's response.</li>
<li>A <a href="#Dialog">Dialog Notification</a>, for Activity-related notifications.</li>
</ul>
<p>This document summarizes each of these techniques for notifying the user and includes
links to full documentation.</p>
<h2 id="Toast">Toast Notification</h2>
<img src="{@docRoot}images/toast.png" alt="" style="float:right" />
<p>A toast notification is a message that pops up on the surface of the window.
It only fills the amount of space required for the message and the user's current
activity remains visible and interactive. The notification automatically fades in and
out, and does not accept interaction events. Because a toast can be created from a background
{@link android.app.Service}, it appears even if the application isn't visible.</p>
<p>A toast is best for short text messages, such as "File saved,"
when you're fairly certain the user is paying attention
to the screen. A toast can not accept user interaction events; if you'd like
the user to respond and take action, consider using a
<a href="#StatusBar">Status Bar Notification</a> instead.</p>
<p>For more information, refer to <a href="toasts.html">Creating Toast Notifications</a>.</p>
<h2 id="StatusBar">Status Bar Notification</h2>
<img src="{@docRoot}images/notifications_window.png" alt="" style="float:right; clear:right;" />
<p>A status bar notification adds an icon to the system's status bar
(with an optional ticker-text message) and an expanded message in the "Notifications" window.
When the user selects the expanded message, Android fires an
{@link android.content.Intent} that is defined by the notification (usually to launch an
{@link android.app.Activity}).
You can also configure the notification to alert the user with a sound, a vibration, and flashing
lights on the device.</p>
<p>This kind of notification is ideal when your application is working in
a background {@link android.app.Service} and needs to
notify the user about an event. If you need to alert the user about an event that occurs
while your Activity is still in focus, consider using a
<a href="#Dialog">Dialog Notification</a> instead.</p>
<p>For more information, refer to
<a href="notifications.html">Creating Status Bar Notifications</a>.</p>
<h2 id="Dialog">Dialog Notification</h2>
<img src="{@docRoot}images/dialog_progress_spinning.png" alt="" style="float:right" />
<p>A dialog is usually a small window that appears in front of the current Activity.
The underlying Activity loses focus and the dialog accepts all user interaction.
Dialogs are normally used
for notifications and short activities that directly relate to the application in progress.</p>
<p>You should use a dialog when you need to show a progress bar or a short
message that requires confirmation from the user (such as an alert with "OK" and "Cancel" buttons).
You can use also use dialogs as integral components
in your application's UI and for other purposes besides notifications.
For a complete discussion on all the available types of dialogs,
including its uses for notifications, refer to
<a href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a>.</p>

View File

@ -0,0 +1,440 @@
page.title=Creating Status Bar Notifications
parent.title=Notifying the User
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ul>
<li>A status bar notification allows your application to notify the user of an event
without interupting their current activity</li>
<li>You can attach an intent to your notification that the system will initiate when the
user clicks it</li>
</ul>
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
<li><a href="#CreateANotification">Creating a Notification</a>
<ol>
<li><a href="#Updating">Updating the notification</a></li>
<li><a href="#Sound">Adding a sound</a></li>
<li><a href="#Vibration">Adding vibration</a></li>
<li><a href="#Lights">Adding flashing lights</a></li>
<li><a href="#More">More features</a></li>
</ol>
</li>
<li><a href="#CustomExpandedView">Creating a Custom Expanded View</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.app.Notification}</li>
<li>{@link android.app.NotificationManager}</li>
</ol>
</div>
</div>
<p>A status bar notification adds an icon to the system's status bar
(with an optional ticker-text message) and an expanded message in the "Notifications" window.
When the user selects the expanded message, Android fires an
{@link android.content.Intent} that is defined by the notification (usually to launch an
{@link android.app.Activity}).
You can also configure the notification to alert the user with a sound, a vibration, and flashing
lights on the device.</p>
<p>A status bar notification should be used for any case in
which a background Service needs to alert the user about an event that requires a response. A background Service
<strong>should never</strong> launch an Activity on its own in order to receive user interaction.
The Service should instead create a status bar notification that will launch the Activity
when selected by the user.</p>
<p>The screenshot below shows the status bar with a notification icon on the left side.</p>
<img src="{@docRoot}images/status_bar.png" alt="" />
<p>The next screenshot shows the notification's expanded message in the "Notifications" window.
The user can reveal the Notifications window by pulling down the status bar
(or selecting <em>Notifications</em> from the Home options menu).</p>
<img src="{@docRoot}images/notifications_window.png" alt="" />
<h2 id="Basics">The Basics</h2>
<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status bar
notification. Because an Activity can perform actions only while it is
active and in focus, you should create your status bar notifications from a
Service. This way, the notification can be created from the background,
while the user is using another application or
while the device is asleep. To create a notification, you must use two
classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.</p>
<p>Use an instance of the {@link android.app.Notification} class to define the properties of your
status bar notification, such as the status bar icon, the expanded message, and extra settings such
as a sound to play. The {@link android.app.NotificationManager} is an Android system service that
executes and manages all Notifications. You do not instantiate the NotificationManager. In order
to give it your Notification, you must retrieve a reference to the NotificationManager with
{@link android.app.Activity#getSystemService(String) getSystemService()} and
then, when you want to notify the user, pass it your Notification object with
{@link android.app.NotificationManager#notify(int,Notification) notify()}. </p>
<p>To create a status bar notification:</p>
<ol>
<li>Get a reference to the NotificationManager:
<pre>
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
</pre>
</li>
<li>Instantiate the Notification:
<pre>
int icon = R.drawable.notification_icon;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
</pre>
</li>
<li>Define the Notification's expanded message and Intent:
<pre>
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
</pre>
</li>
<li>Pass the Notification to the NotificationManager:
<pre>
private static final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
</pre>
<p>That's it. Your user has now been notified.</p>
</li>
</ol>
<h2 id="ManageYourNotifications">Managing your Notifications</h2>
<p>The {@link android.app.NotificationManager} is a system service that manages all
notifications. You must retrieve a reference to it with the
{@link android.app.Activity#getSystemService(String) getSystemService()} method.
For example:</p>
<pre>
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
</pre>
<p>When you want to send your status bar notification, pass the Notification object
to the NotificationManager with {@link android.app.NotificationManager#notify(int,Notification)}.
The first parameter is the unique ID for the Notification and the second is the Notification object.
The ID uniquely identifies the Notification from within your
application. This is necessary if you need to update the Notification or (if
your application manages different kinds of Notifications) select the appropriate action
when the user returns to your application via the Intent defined in the Notification.</p>
<p>To clear the status bar notification when the user selects it from the Notifications
window, add the "FLAG_AUTO_CANCEL" flag to your Notification object. You can also clear it
manually with {@link android.app.NotificationManager#cancel(int)}, passing it the notification ID,
or clear all your Notifications with {@link android.app.NotificationManager#cancelAll()}.</p>
<h2 id="CreateANotification">Creating a Notification</h2>
<p>A {@link android.app.Notification} object defines the details of the notification
message that is displayed in the status bar and "Notifications" window, and any other
alert settings, such as sounds and blinking lights.</p>
<p>A status bar notification <em>requires</em> all of the following:</p>
<ul>
<li>An icon for the status bar</li>
<li>A title and expanded message for the expanded view (unless you define a
<a href="#CustomExpandedView">custom expanded view</a>)</li>
<li>A {@link android.app.PendingIntent}, to be fired when the notification is selected</li>
</ul>
<p>Optional settings for the status bar notification include:</p>
<ul>
<li>A ticker-text message for the status bar</li>
<li>An alert sound</li>
<li>A vibrate setting</li>
<li>A flashing LED setting</li>
</ul>
<p>The starter-kit for a new Notification includes the
{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the
{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)}
method. These define all the required settings for a Notification.
The following snippet demonstrates a basic Notification setup:</p>
<pre>
int icon = R.drawable.notification_icon; // icon from resources
CharSequence tickerText = "Hello"; // ticker-text
long when = System.currentTimeMillis(); // notification time
Context context = getApplicationContext(); // application Context
CharSequence contentTitle = "My notification"; // expanded message title
CharSequence contentText = "Hello World!"; // expanded message text
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// the next two lines initialize the Notification, using the configurations above
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
</pre>
<h3 id="Updating">Updating the notification</h3>
<p>You can update the information in your status bar notification as events
continue to occur in your application. For example, when a new SMS text message arrives
before previous messages have been read, the Messaging application updates the existing
notification to display the total number of new messages received.
This practice of updating an existing Notification is much better than adding new Notifications
to the NotificationManager because it avoids clutter in the Notifications window.</p>
<p>Because each notification is uniquely identified
by the NotificationManager with an integer ID, you can revise the notification by calling
{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
setLatestEventInfo()} with new values, change some field values of the Notification, and then call
{@link android.app.NotificationManager#notify(int,Notification) notify()} again.</p>
<p>You can revise each property with the object member fields
(except for the Context and the expanded message title and text). You should always
revise the text message when you update the notification by calling
{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
setLatestEventInfo()} with new values for <var>contentTitle</var> and <var>contentText</var>.
Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the
notification. (Of course, if you've created a <a href="#CustomExpandedView">custom expanded
view</a>, then updating these title and text values has no effect.)</p>
<h3 id="Sound">Adding a sound</h3>
<p>You can alert the user with the default notification sound
(which is defined by the user) or with a sound specified by your application.</p>
<p>To use the user's default sound, add "DEFAULT_SOUND" to the <var>defaults</var> field:</p>
<pre>
notification.defaults |= Notification.DEFAULT_SOUND;
</pre>
<p>To use a different sound with your notifications, pass a Uri reference to the
<var>sound</var> field.
The following example uses a known audio file saved to the device SD card:</p>
<pre>
notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
</pre>
<p>In the next example, the audio file is chosen from the internal
{@link android.provider.MediaStore.Audio.Media MediaStore}'s {@link android.content.ContentProvider}:</p>
<pre>
notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
</pre>
<p>In this case, the exact ID of the media file ("6") is known and appended to the content
{@link android.net.Uri}. If you don't know the exact ID, you must query all the
media available in the MediaStore with a {@link android.content.ContentResolver}.
See the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
documentation for more information on using a ContentResolver.</p>
<p>If you want the sound to continuously repeat until the user responds to the notification
or the notification is cancelled, add "FLAG_INSISTENT" to the <var>flags</var> field.</p>
<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
"DEFAULT_SOUND", then the default sound overrides any sound defined by the <var>sound</var> field.</p>
<h3 id="Vibration">Adding vibration</h3>
<p>You can alert the user with the the default
vibration pattern or with a vibration pattern defined by your application.</p>
<p>To use the default pattern, add "DEFAULT_VIBRATE" to the <var>defaults</var> field:</p>
<pre>
notification.defaults |= Notification.DEFAULT_VIBRATE;
</pre>
<p>To define your own vibration pattern, pass an array of <em>long</em> values to the
<var>vibrate</var> field:</p>
<pre>
long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate;
</pre>
<p>The long array defines the alternating pattern for the length of vibration off and on
(in milliseconds). The first value is how long to wait (off) before beginning, the second
value is the length of the first vibration, the third is the next length off, and so on.
The pattern can be as long as you like, but it can't be set to repeat.
</p>
<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
"DEFAULT_VIBRATE", then the default vibration overrides any vibration defined by the
<var>vibrate</var> field.</p>
<h3 id="Lights">Adding flashing lights</h3>
<p>To alert the user by flashing LED lights, you can implement the default
light pattern (if available), or define your own color and pattern for the lights.</p>
<p>To use the default light setting, add "DEFAULT_LIGHTS" to the <var>defaults</var> field:</p>
<pre>
notification.defaults |= Notification.DEFAULT_LIGHTS;
</pre>
<p>To define your own color and pattern, define a value for the <var>ledARGB</var> field
(for the color), the <var>ledOffMS</var> field (length of time, in milliseconds, to
keep the light off), the <var>ledOnMS</var> (length of time, in milliseconds, to keep the light on),
and also add "FLAG_SHOW_LIGHTS" to the <var>flags</var> field:</p>
<pre>
notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 300;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
</pre>
<p>In this example, the green light repeatedly flashes on for 300 milliseconds and
turns off for one second. Not every color in the spectrum is supported by the
device LEDs, and not every device supports the same colors, so the hardware
estimates to the best of its ability. Green is the most common notification color.</p>
<h3 id="More">More features</h3>
<p>You can add several more features to your notifications
using Notification fields and flags. Some useful features include the following:</p>
<dl>
<dt>"FLAG_AUTO_CANCEL" flag</dt>
<dd>Add this to the <var>flags</var> field to automatically cancel the notification
after it is selected from the Notifications window.</dd>
<dt>"FLAG_INSISTENT" flag</dt>
<dd>Add this to the <var>flags</var> field to repeat the audio until the
user responds.</dd>
<dt>"FLAG_ONGOING_EVENT" flag</dt>
<dd>Add this to the <var>flags</var> field to group the notification under the "Ongoing"
title in the Notifications window. This indicates that the application is on-going &mdash;
its processes is still running in the background, even when the application is not
visible (such as with music or a phone call).</dd>
<dt>"FLAG_NO_CLEAR" flag</dt>
<dd>Add this to the <var>flags</var> field to indicate that the notification should
<em>not</em> be cleared by the "Clear notifications" button. This is particularly useful if
your notification is on-going.</dd>
<dt><var>number</var> field</dt>
<dd>This value indicates the current number of events represented by the notification.
The appropriate number is overlaid on top of the status bar icon.
If you intend to use this field, then you must start with "1" when the Notification is first
created. (If you change the value from zero to anything greater during an update, the number
is not shown.)</dd>
<dt><var>iconLevel</var> field</dt>
<dd>This value indicates the current level of a
{@link android.graphics.drawable.LevelListDrawable} that is used for the notification icon.
You can animate the icon in the status bar by changing this value to correlate with the
drawable's defined in a LevelListDrawable. See the {@link android.graphics.drawable.LevelListDrawable}
reference for more information.</dd>
</dl>
<p>See the {@link android.app.Notification} class reference for more information about additional
features that you can customize for your application.</p>
<h2 id="CustomExpandedView">Creating a Custom Expanded View</h2>
<img src="{@docRoot}images/custom_message.png" alt="" style="float:right;" />
<p>By default, the expanded view used in the "Notifications" window includes a basic title and text
message. These are defined by the <var>contentTitle</var> and <var>contentText</var>
parameters of the {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
setLatestEventInfo()} method. However, you can also define a custom layout for the expanded view using
{@link android.widget.RemoteViews}. The screenshot to the right shows an example of a
custom expanded view that uses an ImageView and TextView in a LinearLayout.</p>
<p>To define your own layout for the expanded message,
instantiate a {@link android.widget.RemoteViews} object and
pass it to the <var>contentView</var> field of your Notification. Pass the
{@link android.app.PendingIntent} to the <var>contentIntent</var> field.</p>
<p>Creating a custom expanded view is best understood with an example:</p>
<ol>
<li>Create the XML layout for the expanded view.
For example, create a layout file called <code>custom_notification_layout.xml</code> and
build it like so:
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="3dp"
>
&lt;ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#000"
/>
&lt;/LinearLayout>
</pre>
<p>This layout is used for the expanded view,
but the content of the ImageView and TextView still needs to be defined by the application.
RemoteViews offers some convenient methods that allow you to define this content...</p>
</li>
<li>In the application code, use the RemoveViews
methods to define the image and text. Then pass the RemoteViews object to the <var>contentView</var>
field of the Notification, as shown in this example:
<pre>
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view");
notification.contentView = contentView;
</pre>
<p>As shown here, pass the application's package name and the layout
resource ID to the RemoteViews constructor. Then, define the content for the ImageView and TextView,
using the {@link android.widget.RemoteViews#setImageViewResource(int, int) setImageViewResource()}
and {@link android.widget.RemoteViews#setTextViewText(int, CharSequence) setTextViewText()}.
In each case, pass the reference ID of the appropriate View object that you want to set, along with
the value for that View. Finally, the RemoteViews object is passed to the Notification in the
<var>contentView</var> field.</p>
</li>
<li>Because you don't need the
{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
setLatestEventInfo()} method when using a custom view, you must define the Intent for the Notification
with the <var>contentIntent</var> field, as in this example:
<pre>
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
</pre>
</li>
<li>The notification can now be sent as usual:
<pre>mNotificationManager.notify(CUSTOM_VIEW_ID, notification);</pre>
</li>
</ol>
<p>The RemoteViews class also includes methods that you can use to easily add a
{@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
in your notification's expanded view. For more information about creating custom layouts with
RemoteViews, refer to the {@link android.widget.RemoteViews} class reference.</p>
<p class="warning"><strong>Note:</strong>
When creating a custom expanded view, you must take special care to ensure that your
custom layout functions properly in different device orientations and resolutions. While this
advice applies to all View layouts created on Android, it is especially important in this case
because your layout real estate is very restricted. So don't make your custom layout too
complex and be sure to test it in various configurations.</p>

View File

@ -0,0 +1,162 @@
page.title=Creating Toast Notifications
parent.title=Notifying the User
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>Quickview</h2>
<ol>
<li>A toast is a message that appears on the surface of the screen for a moment, but it
does not take focus (or pause the current activity), so it cannot accept user input</li>
<li>You can customize the toast layout to include images</li>
</ol>
<h2>In this document</h2>
<ol>
<li><a href="#Basics">The Basics</a></li>
<li><a href="#Positioning">Positioning your Toast</a></li>
<li><a href="#CustomToastView">Creating a Custom Toast View</a></li>
</ol>
<h2>Key classes</h2>
<ol>
<li>{@link android.widget.Toast}</li>
</ol>
</div>
</div>
<p>A toast notification is a message that pops up on the surface of the window.
It only fills the amount of space required for the message and the user's current
activity remains visible and interactive. The notification automatically fades in and
out, and does not accept interaction events.</p>
<p>The screenshot below shows an example toast notification from the Alarm application.
Once an alarm is turned on, a toast is displayed to assure you that the
alarm was set.</p>
<img src="{@docRoot}images/toast.png" alt="" />
<p>A toast can be created and displayed from an {@link android.app.Activity} or
{@link android.app.Service}. If you create a toast notification from a Service, it
appears in front of the Activity currently in focus.</p>
<p>If user response to the notification is required, consider using a
<a href="notifications.html">Status Bar Notification</a>.</p>
<h2 id="Basics">The Basics</h2>
<p>First, instantiate a {@link android.widget.Toast}
object with one of the {@link android.widget.Toast#makeText(Context,int,int) makeText()} methods.
This method takes three parameters: the application {@link android.content.Context},
the text message, and the duration for the toast. It returns a properly initialized Toast
object. You can display the toast notification with {@link android.widget.Toast#show()},
as shown in the following example:</p>
<pre>
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
</pre>
<p>This example demonstrates everything you need for most toast notifications.
You should rarely need anything else. You may, however, want to position the
toast differently or even use your own layout instead of a simple text message.
The following sections describe how you can do these things.</p>
<p>You can also chain your methods and avoid holding on to the Toast object, like this:</p>
<pre>Toast.makeText(context, text, duration).show();</pre>
<h2 id="Positioning">Positioning your Toast</h2>
<p>A standard toast notification appears near the bottom of the screen, centered horizontally.
You can change this position with the {@link android.widget.Toast#setGravity(int,int,int)}
method. This accepts three parameters: a {@link android.view.Gravity} constant,
an x-position offset, and a y-position offset.</p>
<p>For example, if you decide that the toast should appear in the top-left corner, you can set the
gravity like this:</p>
<pre>
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
</pre>
<p>If you want to nudge the position to the right, increase the value of the second parameter.
To nudge it down, increase the value of the last parameter.
<h2 id="CustomToastView">Creating a Custom Toast View</h2>
<img src="{@docRoot}images/custom_toast.png" alt="" style="float:right" />
<p>If a simple text message isn't enough, you can create a customized layout for your
toast notification. To create a custom layout, define a View layout,
in XML or in your application code, and pass the root {@link android.view.View} object
to the {@link android.widget.Toast#setView(View)} method.</p>
<p>For example, you can create the layout for the toast visible in the screenshot to the right
with the following XML (saved as <em>toast_layout.xml</em>):</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:background="#DAAA"
>
&lt;ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#FFF"
/>
&lt;/LinearLayout>
</pre>
<p>Notice that the ID of the LinearLayout element is "toast_layout". You must use this
ID to inflate the layout from the XML, as shown here:</p>
<pre>
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_layout,
(ViewGroup) findViewById(R.id.toast_layout_root));
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Hello! This is a custom toast!");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
</pre>
<p>First, retrieve the {@link android.view.LayoutInflater} with
{@link android.app.Activity#getLayoutInflater()}
(or {@link android.content.Context#getSystemService(String) getSystemService()}),
and then inflate the layout from XML using
{@link android.view.LayoutInflater#inflate(int, ViewGroup)}. The first parameter
is the layout resource ID and the second is the root View. You can use
this inflated layout to find more View objects in the layout, so now capture and
define the content for the ImageView and TextView elements. Finally, create
a new Toast with {@link android.widget.Toast#Toast(Context)} and set some properties
of the toast, such as the gravity and duration. Then call
{@link android.widget.Toast#setView(View)} and pass it the inflated layout.
You can now display the toast with your custom layout by calling
{@link android.widget.Toast#show()}.</p>
<p class="note"><strong>Note:</strong> Do not use the public constructor for a Toast
unless you are going to define the layout with {@link android.widget.Toast#setView(View)}.
If you do not have a custom layout to use, you must use
{@link android.widget.Toast#makeText(Context,int,int)} to create the Toast.</p>

View File

@ -0,0 +1,390 @@
page.title=Applying Styles and Themes
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#DefiningStyles">Defining Styles</a>
<ol>
<li><a href="#Inheritance">Inheritance</a></li>
<li><a href="#Properties">Style Properties</a></li>
</ol>
</li>
<li><a href="#ApplyingStyles">Applying Styles and Themes to the UI</a>
<ol>
<li><a href="#ApplyAStyle">Apply a style to a View</a></li>
<li><a href="#ApplyATheme">Apply a theme to an Activity or application</a></li>
</ol>
</li>
<li><a href="#PlatformStyles">Using Platform Styles and Themes</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style
and Theme Resources</a></li>
<li>{@link android.R.style} for Android styles and themes</li>
<li>{@link android.R.attr} for all style attributes</li>
</ol>
</div>
</div>
<p>A <strong>style</strong> is a collection of properties that
specify the look and format for a {@link android.view.View} or window.
A style can specify properties such as height, padding, font color, font size,
background color, and much more. A style is defined in an XML resource that is
separate from the XML that specifies the layout.</p>
<p>Styles in Android share a similar philosophy to cascading stylesheets in web
design&mdash;they allow you to separate the design from the
content.</p>
<p>For example, by using a style, you can take this layout XML:</p>
<pre>
&lt;TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#00FF00"
android:typeface="monospace"
android:text="@string/hello" />
</pre>
<p>And turn it into this:</p>
<pre>
&lt;TextView
style="@style/CodeFont"
android:text="@string/hello" />
</pre>
<p>All of the attributes related to style have been removed from the layout XML and put into a
style definition called {@code CodeFont}, which is then applied with the <code>style</code>
attribute. You'll see the definition for this style in the following section.</p>
<p>A <strong>theme</strong> is a style applied to an entire {@link android.app.Activity} or
application, rather than an individual {@link android.view.View} (as in the example above). When a
style is applied as a theme, every View in the Activity or application will apply each style
property that it supports. For example, you can apply the same {@code CodeFont} style
as a theme for an Activity and then all text inside that Activity will have green monospace
font.</p>
<h2 id="DefiningStyles">Defining Styles</h2>
<p>To create a set of styles, save an XML file in the {@code res/values/}
directory of your project. The name of the XML file is arbitrary, but it must use the
{@code .xml} extension and be saved in the {@code res/values/} folder.</p>
<p>The root node of the XML file must be {@code &lt;resources&gt;}.</p>
<p>For each style you want to create, add a {@code &lt;style>} element to the file
with a {@code name} that uniquely identifies the style (this attribute is required).
Then add an {@code &lt;item>} element for each property of that style, with a
{@code name} that declares the style property and a value to go with it (this attribute
is required). The value for the {@code &lt;item>} can
be a keyword string, a hex color, a reference to another resource type, or other value
depending on the style property.
Here's an example file with a single style:</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources&gt;
&lt;style name="CodeFont" parent="@android:style/TextAppearance.Medium"&gt;
&lt;item name="android:layout_width"&gt;fill_parent&lt;/item&gt;
&lt;item name="android:layout_height"&gt;wrap_content&lt;/item&gt;
&lt;item name="android:textColor"&gt;#00FF00&lt;/item&gt;
&lt;item name="android:typeface"&gt;monospace&lt;/item&gt;
&lt;/style&gt;
&lt;/resources&gt;
</pre>
<p>Each child of the {@code &lt;resources>} element is converted into an application resource
object at compile-time, which can be referenced by the value in the {@code &lt;style>} element's
{@code name} attribute. This example style can be referenced from an XML layout as
{@code @style/CodeFont} (as demonstrated in the introduction above).</p>
<p>The <code>parent</code> attribute in the {@code &lt;style>} element is optional and
specifies the resource ID of another style from which this style should inherit
properties. You can then override the inherited style properties if you want to.</p>
<p>Remember, a style that you want to use as an Activity or application theme is defined in XML
exactly the same as a style for a View. A style such as the one defined above can be applied as a
style for a single View or as a theme for an entire Activity or application. How to apply a style
for a single View or as an application theme is discussed later.</p>
<h3 id="Inheritance">Inheritance</h3>
<p>The {@code parent} attribute in the {@code &lt;style>} element lets you specify a style
from which your style should inherit properties.
You can use this to inherit properties from an existing style and
then define only the properties that you want to change or add. You can
inherit from styles that you've created yourself or from styles that are built into the
platform. (See <a href="#PlatformStyles">Using Platform Styles and Themes</a>, below, for
information about inheriting from styles defined by the Android platform.) For example, you can
inherit the Android platform's default text appearance and then modify it:</p>
<pre>
&lt;style name="GreenText" parent="@android:style/TextAppearance"&gt;
&lt;item name="android:textColor"&gt;#00FF00&lt;/item&gt;
&lt;/style&gt;
</pre>
<p>If you want to inherit from styles that you've defined yourself, you <em>do not</em> have to use
the <code>parent</code> attribute. Instead, just prefix the name of the style you want to
inherit to the name of your new style, separated by a period. For example, to create a new style
that inherits the <code>CodeFont</code> style defined above, but make the color red,
you can author the new style like this:</p>
<pre>
&lt;style name="CodeFont.Red"&gt;
&lt;item name="android:textColor"&gt;#FF0000&lt;/item&gt;
&lt;/style&gt;
</pre>
<p>Notice that there is no {@code parent} attribute in the {@code &lt;style&gt;} tag, but because
the {@code name} attribute begins with the {@code CodeFont} style name (which
is a style that you have created), this style inherits all style properties from that style. This
style then overrides the {@code android:textColor} property to make the text red. You can
reference this new style as {@code @style/CodeFont.Red}.</p>
<p>You can continue inheriting like
this as many times as you'd like, by chaining names with periods. For example, you can
extend {@code CodeFont.Red} to be bigger, with:</p>
<pre>
&lt;style name="CodeFont.Red.Big"&gt;
&lt;item name="android:textSize"&gt;30sp&lt;/item&gt;
&lt;/style&gt;
</pre>
<p>This inherits from both {@code CodeFont} and {@code CodeFont.Red} styles, then adds the
{@code android:textSize} property.</p>
<p class="note"><strong>Note:</strong> This technique for inheritance by chaining together
names only works for styles defined by your own resources. You can't inherit Android built-in styles
this way. To reference a built-in style, such as {@link android.R.style#TextAppearance}, you must
use the {@code parent} attribute.</p>
<h3 id="Properties">Style Properties</h3>
<p>Now that you understand how a style is defined, you need to learn what kind
of style properties&mdash;defined by the {@code &lt;item>} element&mdash;are available.
You're probably familiar with some already, such as {@link android.R.attr#layout_width} and
{@link android.R.attr#textColor}. Of course, there are many more style properties you can use.</p>
<p>The best place to find properties that apply to a specific {@link android.view.View} is the
corresponding class reference, which lists all of the supported XML attributes. For example, all of the
attributes listed in the table of
<a href="{@docRoot}reference/android/widget/TextView.html#lattrs">TextView XML
attributes</a> can be used in a style definition for a {@link android.widget.TextView} element (or one of
its subclasses). One of the attributes listed in the reference is <a
href="{@docRoot}reference/android/widget/TextView.html#attr_android:inputType">{@code
android:inputType}</a>, so where you might normally place the <a
href="{@docRoot}reference/android/widget/TextView.html#attr_android:inputType">{@code
android:inputType}</a>
attribute in an {@code &lt;EditText>} element, like this:</p>
<pre>
&lt;EditText
android:inputType="number"
... />
</pre>
<p>You can instead create a style for the {@link android.widget.EditText} element that includes this property:</p>
<pre>
&lt;style name="Numbers">
&lt;item name="android:inputType">number&lt;/item>
...
&lt;/style>
</pre>
<p>So your XML for the layout can now implement this style:</p>
<pre>
&lt;EditText
style="@style/Numbers"
... />
</pre>
<p>This simple example may look like more work, but when you add more style properties and
factor-in the ability to re-use the style in various places, the pay-off can be huge.</p>
<p>For a reference of all available style properties, see the {@link android.R.attr}
reference. Keep in mind that all View objects don't accept all the same style attributes, so you
should normally refer to the specific {@link android.view.View} class for supported style
properties. However, if you
apply a style to a View that does not support all of the style properties, the View will
apply only those properties that are supported and simply ignore the others.</p>
<p>Some style properties, however, are not supported by any View element and can only be applied
as a theme. These style properties apply to the entire window and not to any type of View.
For example, style properties for a theme can hide the application title, hide the status bar,
or change the window's background. These kind of style properties do not belong to any View object.
To discover these theme-only style properties, look at the {@link android.R.attr} reference for
attributes that begin with {@code window}. For instance, {@code windowNoTitle} and {@code
windowBackground} are style properties that are effective only when the style is applied as
a theme to an Activity or application. See the next section for information about applying a
style as a theme.</p>
<p class="note"><strong>Note:</strong> Don't forget to prefix the property names in each
{@code &lt;item&gt;} element with the <code>android:</code> namespace. For example:
{@code &lt;item name="android:inputType">}.</p>
<h2 id="ApplyingStyles">Applying Styles and Themes to the UI</h2>
<p>There are two ways to set a style:</p>
<ul>
<li>To an individual View, by adding the <code>style</code> attribute to a View
element in the XML for your layout.</li>
<li>Or, to an entire Activity or application, by adding the <code>android:theme</code>
attribute to the <code>&lt;activity></code> or <code>&lt;application></code> element
in the Android manifest.</li>
</ul>
<p>When you apply a style to a single {@link android.view.View} in the layout, the properties
defined by the style are applied only to that {@link android.view.View}. If a style is applied to a
{@link android.view.ViewGroup}, the child {@link android.view.View} elements will
<strong>not</strong> inherit the style properties&mdash;only the element to which you directly apply
the style will apply its properties. However, you <em>can</em> apply a style so that it
applies to all {@link android.view.View} elements&mdash;by applying the style as a theme.</p>
<p>To apply a style definition as a theme, you must apply the style to an
{@link android.app.Activity} or application in the Android manifest. When you do so,
every {@link android.view.View} within the Activity or
application will apply each property that it supports. For example, if you apply the {@code
CodeFont} style from the previous examples to an Activity, then all View elements
that support the text style properties will apply them. Any View that does not support
the properties will ignore them. If a View supports only some of the properties, then
it will apply only those properties.</p>
<h3 id="ApplyAStyle">Apply a style to a View</h3>
<p>Here's how to set a style for a View in the XML layout:</p>
<pre>
&lt;TextView
style="@style/CodeFont"
android:text="@string/hello" />
</pre>
<p>Now this TextView will be styled as defined by the style named {@code CodeFont}.
(See the sample above, in <a href="#DefiningStyles">Defining Styles</a>.)</p>
<p class="note"><strong>Note:</strong> The <code>style</code> attribute
does <em>not</em> use the <code>android:</code> namespace prefix.</p>
<h3 id="ApplyATheme">Apply a theme to an Activity or application</h3>
<p>To set a theme for all the activities of your application, open the {@code AndroidManifest.xml} file and
edit the <code>&lt;application></code> tag to include the <code>android:theme</code> attribute with the
style name. For example:</p>
<pre>
&lt;application android:theme="@style/CustomTheme">
</pre>
<p>If you want a theme applied to just one Activity in your application, then add the
<code>android:theme</code> attribute to the <code>&lt;activity></code> tag instead.</p>
<p>Just as Android provides other built-in resources, there are many pre-defined themes that you can use, to avoid
writing them yourself. For example, you can use the {@code Dialog} theme and make your Activity
appear like a dialog box:</p>
<pre>
&lt;activity android:theme="@android:style/Theme.Dialog">
</pre>
<p>Or if you want the background to be transparent, use the Translucent theme:</p>
<pre>
&lt;activity android:theme="@android:style/Theme.Translucent">
</pre>
<p>If you like a theme, but want to tweak it, just add the theme as the <code>parent</code>
of your custom theme. For example, you can modify the traditional dialog theme to use your own
background image like this:</p>
<pre>
&lt;style name="CustomDialogTheme" parent="@android:style/Theme.Dialog">
&lt;item name="android:windowBackground">@drawable/custom_dialog_background&lt;/item>
&lt;/style>
</pre>
<p>Now use {@code CustomDialogTheme} instead of {@code Theme.Dialog} inside the Android
Manifest:</p>
<pre>
&lt;activity android:theme="@style/CustomDialogTheme">
</pre>
<!-- This currently has some bugs
<h3 id="setThemeFromTheApp">Set the theme from the application</h3>
<p>We recommend that you set your themes in you Android manifest, as described above, because it's simple and
keeps your program code focused on application functionality, rather than style. But if it's necessary
for you to change your theme programatically (perhaps based on a user preference), you can.</p>
<p>To set the theme in your program code, use the {@link android.content.ContextWrapper#setTheme(int)}
method and pass it the theme resource ID. Note that, when doing so, you must be sure to set the theme <em>before</em>
instantiating any Views in the context, for example, before calling
<code>setContentView(View)</code> or <code>inflate(int, ViewGroup)</code>. This ensures that
the system applies the same theme for all of your UI screens. Here's an example:</p>
<pre>
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
setTheme(android.R.style.Theme_Light);
setContentView(R.layout.linear_layout_3);
}
</pre>
<p>If you are considering loading a theme programmatically for the main
screen of your application, note that the theme would not be applied
in any animations the system would use to start the activity, which
would take place before your application opens. In most cases, if
you want to apply a theme to your main screen, doing so in XML
is a better approach. </p>
-->
<h2 id="PlatformStyles">Using Platform Styles and Themes</h2>
<p>The Android platform provides a large collection of styles and themes that you can
use in your applications. You can find a reference of all available styles in the
{@link android.R.style} class. To use the styles listed here, replace all underscores in
the style name with a period. For example, you can apply the
{@link android.R.style#Theme_NoTitleBar} theme with
{@code "@android:style/Theme.NoTitleBar"}.</p>
<p>The {@link android.R.style} reference, however, is not well documented and does not
thoroughly describe the styles, so viewing the actual source code for these styles and
themes will give you a better understanding of what style properties each one provides.
For a better reference to the Android styles and themes, see the following source code:</p>
<ul>
<li><a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/res/res/values/styles.xml;h=d7b654e49809cb97a35682754b1394af5c8bc88b;hb=HEAD">Android Styles (styles.xml)</a></li>
<li><a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/res/res/values/themes.xml;h=6b3d7407d1c895a3c297e60d5beac98e2d34c271;hb=HEAD">Android Themes (themes.xml)</a></li>
</ul>
<p>These files will help you learn through example. For instance, in the Android themes source code,
you'll find a declaration for <code>&lt;style name="Theme.Dialog"&gt;</code>. In this definition,
you'll see all of the properties that are used to style dialogs that are used by the Android
framework.</p>
<p>For more information about the syntax used to create styles in XML, see
<a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Available Resource Types:
Style and Themes</a>.</p>
<p>For a reference of available style attributes that you can use to define a style or theme
(e.g., "windowBackground" or "textAppearance"), see {@link android.R.attr} or the respective
View class for which you are creating a style.</p>

View File

@ -0,0 +1,283 @@
page.title=Handling UI Events
parent.title=User Interface
parent.link=index.html
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#EventListeners">Event Listeners</a></li>
<li><a href="#EventHandlers">Event Handlers</a></li>
<li><a href="#TouchMode">Touch Mode</a></li>
<li><a href="#HandlingFocus">Handling Focus</a></li>
</ol>
<h2>Related tutorials</h2>
<ol>
<li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Form Stuff</a></li>
</ol>
</div>
</div>
<p>On Android, there's more than one way to intercept the events from a user's interaction with your application.
When considering events within your user interface, the approach is to capture the events from
the specific View object that the user interacts with. The View class provides the means to do so.</p>
<p>Within the various View classes that you'll use to compose your layout, you may notice several public callback
methods that look useful for UI events. These methods are called by the Android framework when the
respective action occurs on that object. For instance, when a View (such as a Button) is touched,
the <code>onTouchEvent()</code> method is called on that object. However, in order to intercept this, you must extend
the class and override the method. However, extending every View object
in order to handle such an event would not be practical. This is why the View class also contains
a collection of nested interfaces with callbacks that you can much more easily define. These interfaces,
called <a href="#EventListeners">event listeners</a>, are your ticket to capturing the user interaction with your UI.</p>
<p>While you will more commonly use the event listeners to listen for user interaction, there may
come a time when you do want to extend a View class, in order to build a custom component.
Perhaps you want to extend the {@link android.widget.Button}
class to make something more fancy. In this case, you'll be able to define the default event behaviors for your
class using the class <a href="#EventHandlers">event handlers</a>.</p>
<h2 id="EventListeners">Event Listeners</h2>
<p>An event listener is an interface in the {@link android.view.View} class that contains a single
callback method. These methods will be called by the Android framework when the View to which the listener has
been registered is triggered by user interaction with the item in the UI.</p>
<p>Included in the event listener interfaces are the following callback methods:</p>
<dl>
<dt><code>onClick()</code></dt>
<dd>From {@link android.view.View.OnClickListener}.
This is called when the user either touches the item
(when in touch mode), or focuses upon the item with the navigation-keys or trackball and
presses the suitable "enter" key or presses down on the trackball.</dd>
<dt><code>onLongClick()</code></dt>
<dd>From {@link android.view.View.OnLongClickListener}.
This is called when the user either touches and holds the item (when in touch mode), or
focuses upon the item with the navigation-keys or trackball and
presses and holds the suitable "enter" key or presses and holds down on the trackball (for one second).</dd>
<dt><code>onFocusChange()</code></dt>
<dd>From {@link android.view.View.OnFocusChangeListener}.
This is called when the user navigates onto or away from the item, using the navigation-keys or trackball.</dd>
<dt><code>onKey()</code></dt>
<dd>From {@link android.view.View.OnKeyListener}.
This is called when the user is focused on the item and presses or releases a key on the device.</dd>
<dt><code>onTouch()</code></dt>
<dd>From {@link android.view.View.OnTouchListener}.
This is called when the user performs an action qualified as a touch event, including a press, a release,
or any movement gesture on the screen (within the bounds of the item).</dd>
<dt><code>onCreateContextMenu()</code></dt>
<dd>From {@link android.view.View.OnCreateContextMenuListener}.
This is called when a Context Menu is being built (as the result of a sustained "long click"). See the discussion
on context menus in <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Creating Menus</a> for more information.</dd>
</dl>
<p>These methods are the sole inhabitants of their respective interface. To define one of these methods
and handle your events, implement the nested interface in your Activity or define it as an anonymous class.
Then, pass an instance of your implementation
to the respective <code>View.set...Listener()</code> method. (E.g., call
<code>{@link android.view.View#setOnClickListener(View.OnClickListener) setOnClickListener()}</code>
and pass it your implementation of the {@link android.view.View.OnClickListener OnClickListener}.)</p>
<p>The example below shows how to register an on-click listener for a Button. </p>
<pre>
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
</pre>
<p>You may also find it more convenient to implement OnClickListener as a part of your Activity.
This will avoid the extra class load and object allocation. For example:</p>
<pre>
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
...
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this);
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
...
}
</pre>
<p>Notice that the <code>onClick()</code> callback in the above example has
no return value, but some other event listener methods must return a boolean. The reason
depends on the event. For the few that do, here's why:</p>
<ul>
<li><code>{@link android.view.View.OnLongClickListener#onLongClick(View) onLongClick()}</code> -
This returns a boolean to indicate whether you have consumed the event and it should not be carried further.
That is, return <em>true</em> to indicate that you have handled the event and it should stop here;
return <em>false</em> if you have not handled it and/or the event should continue to any other
on-click listeners.</li>
<li><code>{@link android.view.View.OnKeyListener#onKey(View,int,KeyEvent) onKey()}</code> -
This returns a boolean to indicate whether you have consumed the event and it should not be carried further.
That is, return <em>true</em> to indicate that you have handled the event and it should stop here;
return <em>false</em> if you have not handled it and/or the event should continue to any other
on-key listeners.</li>
<li><code>{@link android.view.View.OnTouchListener#onTouch(View,MotionEvent) onTouch()}</code> -
This returns a boolean to indicate whether your listener consumes this event. The important thing is that
this event can have multiple actions that follow each other. So, if you return <em>false</em> when the
down action event is received, you indicate that you have not consumed the event and are also
not interested in subsequent actions from this event. Thus, you will not be called for any other actions
within the event, such as a finger gesture, or the eventual up action event.</li>
</ul>
<p>Remember that key events are always delivered to the View currently in focus. They are dispatched starting from the top
of the View hierarchy, and then down, until they reach the appropriate destination. If your View (or a child of your View)
currently has focus, then you can see the event travel through the <code>{@link android.view.View#dispatchKeyEvent(KeyEvent)
dispatchKeyEvent()}</code> method. As an alternative to capturing key events through your View, you can also receive
all of the events inside your Activity with <code>{@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown()}</code>
and <code>{@link android.app.Activity#onKeyUp(int,KeyEvent) onKeyUp()}</code>.</p>
<p class="note"><strong>Note:</strong> Android will call event handlers first and then the appropriate default
handlers from the class definition second. As such, returning <em>true</em> from these event listeners will stop
the propagation of the event to other event listeners and will also block the callback to the
default event handler in the View. So be certain that you want to terminate the event when you return <em>true</em>.</p>
<h2 id="EventHandlers">Event Handlers</h2>
<p>If you're building a custom component from View, then you'll be able to define several callback methods
used as default event handlers.
In the document on <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>,
you'll learn see some of the common callbacks used for event handling, including:</p>
<ul>
<li><code>{@link android.view.View#onKeyDown}</code> - Called when a new key event occurs.</li>
<li><code>{@link android.view.View#onKeyUp}</code> - Called when a key up event occurs.</li>
<li><code>{@link android.view.View#onTrackballEvent}</code> - Called when a trackball motion event occurs.</li>
<li><code>{@link android.view.View#onTouchEvent}</code> - Called when a touch screen motion event occurs.</li>
<li><code>{@link android.view.View#onFocusChanged}</code> - Called when the view gains or loses focus.</li>
</ul>
<p>There are some other methods that you should be aware of, which are not part of the View class,
but can directly impact the way you're able to handle events. So, when managing more complex events inside
a layout, consider these other methods:</p>
<ul>
<li><code>{@link android.app.Activity#dispatchTouchEvent(MotionEvent)
Activity.dispatchTouchEvent(MotionEvent)}</code> - This allows your {@link
android.app.Activity} to intercept all touch events before they are dispatched to the window.</li>
<li><code>{@link android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)
ViewGroup.onInterceptTouchEvent(MotionEvent)}</code> - This allows a {@link
android.view.ViewGroup} to watch events as they are dispatched to child Views.</li>
<li><code>{@link android.view.ViewParent#requestDisallowInterceptTouchEvent(boolean)
ViewParent.requestDisallowInterceptTouchEvent(boolean)}</code> - Call this
upon a parent View to indicate that it should not intercept touch events with <code>{@link
android.view.ViewGroup#onInterceptTouchEvent(MotionEvent)}</code>.</li>
</ul>
<h2 id="TouchMode">Touch Mode</h2>
<p>
When a user is navigating a user interface with directional keys or a trackball, it is
necessary to give focus to actionable items (like buttons) so the user can see
what will accept input. If the device has touch capabilities, however, and the user
begins interacting with the interface by touching it, then it is no longer necessary to
highlight items, or give focus to a particular View. Thus, there is a mode
for interaction named "touch mode."
</p>
<p>
For a touch-capable device, once the user touches the screen, the device
will enter touch mode. From this point onward, only Views for which
{@link android.view.View#isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
Other Views that are touchable, like buttons, will not take focus when touched; they will
simply fire their on-click listeners when pressed.
</p>
<p>
Any time a user hits a directional key or scrolls with a trackball, the device will
exit touch mode, and find a view to take focus. Now, the user may resume interacting
with the user interface without touching the screen.
</p>
<p>
The touch mode state is maintained throughout the entire system (all windows and activities).
To query the current state, you can call
{@link android.view.View#isInTouchMode} to see whether the device is currently in touch mode.
</p>
<h2 id="HandlingFocus">Handling Focus</h2>
<p>The framework will handle routine focus movement in response to user input.
This includes changing the focus as Views are removed or hidden, or as new
Views become available. Views indicate their willingness to take focus
through the <code>{@link android.view.View#isFocusable()}</code> method. To change whether a View can take
focus, call <code>{@link android.view.View#setFocusable(boolean) setFocusable()}</code>. When in touch mode,
you may query whether a View allows focus with <code>{@link android.view.View#isFocusableInTouchMode()}</code>.
You can change this with <code>{@link android.view.View#setFocusableInTouchMode(boolean) setFocusableInTouchMode()}</code>.
</p>
<p>Focus movement is based on an algorithm which finds the nearest neighbor in a
given direction. In rare cases, the default algorithm may not match the
intended behavior of the developer. In these situations, you can provide
explicit overrides with the following XML attributes in the layout file:
<var>nextFocusDown</var>, <var>nextFocusLeft</var>, <var>nextFocusRight</var>, and
<var>nextFocusUp</var>. Add one of these attributes to the View <em>from</em> which
the focus is leaving. Define the value of the attribute to be the id of the View
<em>to</em> which focus should be given. For example:</p>
<pre>
&lt;LinearLayout
android:orientation="vertical"
... >
&lt;Button android:id="@+id/top"
android:nextFocusUp="@+id/bottom"
... />
&lt;Button android:id="@+id/bottom"
android:nextFocusDown="@+id/top"
... />
&lt;/LinearLayout>
</pre>
<p>Ordinarily, in this vertical layout, navigating up from the first Button would not go
anywhere, nor would navigating down from the second Button. Now that the top Button has
defined the bottom one as the <var>nextFocusUp</var> (and vice versa), the navigation focus will
cycle from top-to-bottom and bottom-to-top.</p>
<p>If you'd like to declare a View as focusable in your UI (when it is traditionally not),
add the <code>android:focusable</code> XML attribute to the View, in your layout declaration.
Set the value <var>true</var>. You can also declare a View
as focusable while in Touch Mode with <code>android:focusableInTouchMode</code>.</p>
<p>To request a particular View to take focus, call <code>{@link android.view.View#requestFocus()}</code>.</p>
<p>To listen for focus events (be notified when a View receives or looses focus), use
<code>{@link android.view.View.OnFocusChangeListener#onFocusChange(View,boolean) onFocusChange()}</code>,
as discussed in the <a href="#EventListeners">Event Listeners</a> section, above.</p>
<!--
<h2 is="EventCycle">Event Cycle</h2>
<p>The basic cycle of a View is as follows:</p>
<ol>
<li>An event comes in and is dispatched to the appropriate View. The View
handles the event and notifies any listeners.</li>
<li>If, in the course of processing the event, the View's bounds may need
to be changed, the View will call {@link android.view.View#requestLayout()}.</li>
<li>Similarly, if in the course of processing the event the View's appearance
may need to be changed, the View will call {@link android.view.View#invalidate()}.</li>
<li>If either {@link android.view.View#requestLayout()} or {@link android.view.View#invalidate()} were called,
the framework will take care of measuring, laying out, and drawing the tree
as appropriate.</li>
</ol>
<p class="note"><strong>Note:</strong> The entire View tree is single threaded. You must always be on
the UI thread when calling any method on any View.
If you are doing work on other threads and want to update the state of a View
from that thread, you should use a {@link android.os.Handler}.
</p>
-->