Tải bản đầy đủ
5 Removing, showing, and hiding the action bar

5 Removing, showing, and hiding the action bar

Tải bản đầy đủ

576

CHAPTER 21

Android 3.0 action bar

Listing 21.16 Specifying a theme

package="com.cenriqueortiz.androidinaction"
android:versionCode="1"
android:versionName="1.0">


android:label="@string/app_name"
android:icon="@drawable/manninglogo"
android:theme="@style/ThemeWithActionBar">

B

Assign theme

:

This example assigns the theme at the application level (and thus all actions within)
B. Remember, though, that by targeting Android 3.0 (via the minimum and target
SDK versions previously covered in the chapter), Android will automatically assign the
holographic theme with an action bar.
The theme style referenced in the manifest must be defined. You add custom
theme styles to the style.xml file in a manner similar to how styles are defined in
Android in general.
The list of theme-styleable items is extensive; Android is flexible when it comes to
customizing themes. Following are some examples of commonly used theme style
items:
 Action bar styling

• android:actionBarTabStyle—Lets you customize the action bar tab by
specifying your own style
• android:actionBarTabTextStyle—Lets you customize the action bar tab
text by specifying your own text style
 Text
• android:textColor—Customizes the foreground text color
• android:textSize—Customizes the text size (remember to use sp for scaleindependent pixels when specifying font sizes)
• android:typeface—Specifies the font type
 Other styling
• android:listChoiceIndicatorMultiple—Sets the drawable for multiplechoice indicators
• android:listChoiceIndicatorSingle—Sets the drawable for single-choice
indicators
• android:selectableItemBackground—Sets the background drawable for
standalone items that need focus/pressed states
• android:popupMenuStyle—Sets the style of pop-up menus

577

Action bar styling

• android:dropDownListViewStyle—Specifies the style for drop-down list
menus
• android:actionDropDownStyle—Overrides the default drop-down list style
for the overflow menu and drop-down navigation
The next listing shows an example of how to define the theme style in style.xml.
Listing 21.17 Defining the theme style (in style.xml)


The theme style inherits its characteristics from the theme parent.
Similarly, you can customize the holographic theme, defined by the parent Theme
.Holo or one of its subclasses, such as Theme.Holo.Light (see the following listing).
Listing 21.18 Customizing the holographic theme






B

Set bar text style

C

Set tab style



This example sets the theme style by inheriting from Theme.Holo and overrides various attributes such as the bar text style B and the tab style C.
For a complete list of theme styling items that can be configured, see http://
mng.bz/Dy2M and search for styling items that begin with the prefix Theme_.

578

CHAPTER 21

Android 3.0 action bar

21.7 Summary
This chapter covered the action bar in detail. The action bar offers application control by providing navigation options, widgets, and other contextual information at the
top of the screen, using a consistent approach across applications. This behavioral
consistency results in a familiar approach to application control and navigation and
gives you quick access to actions regardless of the nature of the application.

Drag-and-drop

This chapter covers
 The drag-and-drop classes
 Drag-and-drop operations
 The shadow builder
 Listening for drag-and-drop events

Starting with Android 3.0 (API 11), developers can add drag-and-drop capabilities
to applications. Drag-and-drop support is one of the neat features added in
Android 3.0, a natural addition to touch-based user interfaces and tablets.
Android 3.0 provides a complete framework for drag-and-drop that consists of multiple classes, events, and operations. Related to drag-and-drop are copy-and-paste
operations. Although copy and paste has been around since API 1, a much richer
clipboard API has been introduced in API 11.
Drag-and-drop is a touch-based gesture. With drag-and-drop gestures, you can
allow users to move data across views that reside within in the same layout: for
example, to select data items in one view and drop them onto a different view for
the purpose of sharing or synchronizing data items. Or you can use the drag-anddrop gesture itself to trigger a specific action against the dragged item: for example, viewing the selected item’s details. A typical drag-and-drop operation is shown
in figure 22.1.

579

580

CHAPTER 22

Drag-and-drop

Layout
View 1
Data

Data
Move
Trigger
action

Figure 22.1

View 2
Data

Dragging and dropping data between Views

The drag-and-drop operation starts when the user selects a source item (view) and
begins dragging it onto a destination view; note that both views must be in the same
layout. The dragged item has a shadow that provides visual feedback about the item
being dragged during the operation.
Drag-and-drop operations are a bit involved. There is a drag-and-drop framework
that involves a number of different classes, and the operation itself involves multiple
steps. The next section describes the drag-and-drop operations and the related classes
in more detail.

22.1 The drag-and-drop classes
The drag-and-drop framework involves a number of classes, some pre–Android 3.0,
that all together allow for drag-and-drop operations to take place:
 The source and destination view
 OnLongClickListener to detect when a view has been clicked and held
 OnDragListener to listen for drag events
 DragEvent, which is generated during the drag-and-drop operation
 A DragShadowBuilder that is called to generate the drag shadow for the

dragged item
 ClipData and ClipDescription, which are stored in the system clipboard during the operation
 ContentProvider for drag-and-drop operations of complex data-types
With Android 3.0, the View class has been extended in support of drag-and-drop.
Table 22.1 shows the View-related classes hat are part of the drag-and-drop framework.

581

Drag-and-drop operations
Table 22.1

android.view.View-related drag-and-drop classes
Classes

Description

android.view.View.OnLongClickListener

Listener interface that is called when the user
has performed a long click (clicked the view and
held). It’s common to use long presses to indicate the start of the drag-and-drop operation.

android.view.View.DragShadowBuilder

A class for creating the shadow image that the
system displays during the drag-and-drop
operation.

android.view.View.OnDragListener

Listener interface that is called when a drag
event is being dispatched to this view.

android.view.DragEvent

A class that represents a drag-and-drop event
(about the operation and underlying data) that is
sent out by the system at various times during a
drag-and-drop operation, and received either by
the drag event listener or the view’s
onDragEvent() callback method. See section
22.6.1 for information about when to use the
listener versus the callback.

As previously mentioned, Android 3.0 also introduced a richer copy-and-paste API.
Drag-and-drop uses the copy-and-paste API underneath—the drag operation itself is
about selecting (copying and moving) data from a source and dropping (transferring
or pasting) the data onto a target. The following list summarizes the copy-and-paste
classes that are used for drag-and-drop operations:
 android.content.ClipboardManager—The manager for placing and retriev-

ing clipped data in the global clipboard
 android.content.ClipData—Clipped data on the clipboard; it can hold one

or more representations of an item of data (ClipData.Item)
 android.content.ClipData.Item—A single item of clipped data (ClipData)
 android.content.ClipDescription—Metadata that describes the contents of

ClipData

Note that the API 11 android.content.ClipboardManager replaces the API Level 1
android.text.ClipboardManager. The latter is now deprecated.
The data being transferred during the drag-and-drop operation can be simple
(such as text or URIs) or complex. The clipboard provides a set of methods to handle
simple data, but for complex data, you use ContentProvider. Content providers are
covered in chapter 5.

22.2 Drag-and-drop operations
A drag-and-drop operation consists of a number of steps, some performed by the user,
others by the application, and others by the system, as illustrated in figure 22.2.

582

CHAPTER 22

Application

User

User initiates
the drag
operation

Data

Drag-and-drop

View

System

Screen

Calls startDrag() to start drop operation,
passing data and shadow builder
ACTION_DRAG_STARTED event
(to all Views in current layout)
Return True if accepting operation
and continue receiving subsequent events,
false otherwise

Drag shadow
Continuing
to drag
shadow
Drag shadow
intersects
View’s
bounding box

ACTION_DRAG_ENTERED event
(when it enters bounding box)
ACTION_DRAG_LOCATION events
(while still within bounding box)
ACTION_DRAG_EXITED event
(only if exiting bounding box)

User releases
the shadow
within
the View

Drop
shadow

ACTION_DROP event
(user drops drag shadow)
ACTION_DRAG_ENDED event

Figure 22.2

Drag-and-drop sequence diagram

As you can see, many drag events are triggered during the drag operation. The operation is initiated when the user performs the gesture to start the drag, typically a longpress click that the application is listening to, and for which the application calls the
view’s startDrag() method:
public final boolean startDrag (
ClipData data,
View.DragShadowBuilder shadowBuilder
Object myLocalState,
int flags)

This method must be invoked to start the drag operation. It signals to other views in
the same layout that a drag operation has been initiated. Those views must determine
whether they want to participate on the drop operation. The method startDrag()
takes for input the following arguments:
 ClipData data is the data object to be transferred.
 View.DragShadowBuilder shadowBuilder is the object for building the drag

shadow.

583

The shadow builder

 Object myLocalState is an optional data object that is sent as part of the Drag-

Event object generated from the start-drag operation. It’s a simple or light-

weight mechanism to pass internal local state or information such as state or
flags to the destination view.
 int flags are drag-and-drop control flags; no flags are currently defined, and
they should be set to 0.
This method returns true if the start-drag completes successfully and false otherwise, indicating that the system was unable to start the drag operation (for example,
due to out-of-memory or other errors during the copy) and thus no drag operation is
in progress.
Using the startDrag() method is covered in the section “Starting Drag Operations.” First, the following section introduces drag-and-drop shadows and builders.

22.3 The shadow builder
An important aspect of the drag-and-drop operation is the visual feedback provided
during the drag or data move. When the drag operation is started for a given view by
calling the startDrag() method, a View.DragShadowBuilder callback is specified.
The DragShadowBuilder is called by the system to generate a drag shadow for the view
being dragged.
DragShadowBuilder defines two kinds of constructors: one that takes a View for an
argument, and a no-argument constructor with no associated view. DragShadowBuilder defines three methods:
 getView()—Returns the view associated with the shadow builder
 onDragShadow(Canvas canvas)—Draws the shadow image
 onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)—

Provides the metrics for the shadow image
The following example shows a shadow builder that implements the shadow-builder
constructor, onDragShadow(), and onProvideShadowMetrics() methods.
Listing 22.1 Example shadow builder
private static class MyDragShadowBuilder extends View.DragShadowBuilder {
private static Drawable mShadow;
public MyDragShadowBuilder(View v) {
super(v);
mShadow = new ColorDrawable(Color.LTGRAY);
}

B

Initialize
View.DragShadowBuilder
superclass

@Override
public void onProvideShadowMetrics (Point size, Point touch) {
int width = getView().getWidth();
Define
int height = getView().getHeight();
onProvideShadowMetrics
mShadow.setBounds(0, 0, width, height);
size.set(width, height);
touch.set(width/2, height/2);
}

C

584

CHAPTER 22

Drag-and-drop

@Override
public void onDrawShadow(Canvas canvas) {
super.onDrawShadow(canvas);
mShadow.draw(canvas);
getView().draw(canvas);
}

D

Define callback
to draw shadow

}

Drag shadow builders must extend View.DragShadowBuilder and initialize the superclass with the view to be dragged B. During initialization, to keep the example simple, we define a shadow as a ColorDrawable of light gray color. The shadow size is
defined during the onProvideShadowMetrics() callback, and in this example C is
given the same dimension as the dragged view and a touchpoint that is in the middle
of the dragged view. When it’s time to draw the shadow, onDrawShadow() is called on
which the super onDrawShadow() is called D, and both the shadow’s and view’s
draw() method are called. The drag shadow is drawn during the drag-and-drop process until it’s dropped.
The result is shown in figure 22.3, where you can see the light-gray drag shadow
that is being dragged from the summary ListFragment on the left onto the WebViewFragment on the right. The dragged data is a URL that is loaded from the selected list
item view, which is then transferred to the web view when dropped.
To make all this work, the application must handle a number of drag events that
are triggered during the life of the drag operation. The next sections cover drag
events, how to listen for and handle events, as well as how to copy and transfer data
during the drag-and-drop operation.

Figure 22.3

Dragging and dropping data between views

Drag events

585

22.4 Drag events
When the drag operation has started, and while the user drags the drag shadow, the
system dispatches events to all views that are listening for drag-and-drop operation
events: that is, if the view has indicated that it wants to receive events, as described
shortly.
An android.view.DragEvent represents events that are dispatched by the system
during the drag-and-drop operation as illustrated in the figure 22.2 sequence diagram. When a view receives an event, it must call the event’s getAction() method to
get the event’s action type, which indicates the state of the operation, again as illustrated in the sequence diagram in figure 22.2. By reacting to the various events, the
application and views can provide visual feedback when the drag begins, crosses view
boundaries, and completes. The currently supported event actions are as follows:
 ACTION_DRAG_STARTED—A drag-and-drop operation has begun. Of great impor-








tance is how to respond to ACTION_DRAG_STARTED. To accept the drop operation
and continue receiving further drag events, true must be returned in response
to ACTION_DRAG_STARTED.
ACTION_DRAG_ENTERED—The drag point has entered the view’s bounding box.
ACTION_DRAG_LOCATION—One or more of these events are sent by the system
after ACTION_DRAG_ENTERED and while the drag shadow is within a given view’s
bounding box.
ACTION_DRAG_EXITED—The drag shadow has moved outside the view’s bounding box. This event is received after an ACTION_DRAG_ENTERED and at least one
ACTION_DRAG_LOCATION have been received. After exit, no more ACTION_DRAG
_LOCATION events are sent to the view unless it’s re-entered (that is,
ACTION_DRAG_ENTERED, and the cycle repeats).
ACTION_DROP—The user has released the drag shadow, and the drag point is
within this view’s bounding box. This event is sent by the system only if this view
previously accepted the drop operation by returning true in response to
ACTION_DRAG_STARTED. A call to the event’s getX() and getY() methods
returns the X and Y position of the drag point at the moment of the drop.
This event isn’t sent by the system if the user releases the shadow on views
that aren’t listening for events or on empty areas on the user interface.

 ACTION_DRAG_ENDED—The drag-and-drop operation has ended. This event is

also sent if the user releases the shadow on views that aren’t listening for events
or empty areas on the user interface.
In summary, drag-and-drop events can be grouped based on their purpose:
 For handling drag-and-drop data—ACTION_DRAG_STARTED and ACTION_DROP

ACTION_DRAG_STARTED is generated when the drag operation has started.
ACTION_DROP is generated when the operation has ended with the user per-

forming the drop, so that the application can extract the transferred data.

586

CHAPTER 22

Drag-and-drop

 For

changing the view appearance—ACTION_DRAG_ENTERED,
_LOCATION, ACTION_DRAG_EXITED, and ACTION_DRAG_ENDED

ACTION_DRAG

During the drag-and-drop operation, these events are generated, allowing
the application to change the appearance of views as the drag shadow enters
(ACTION_DRAG_ENTERED) or exits (ACTION_DRAG_EXITED) the target views or
touches parts of a view, or the operation completes (ACTION_DRAG_ENDED).
Now that you’ve seen the different kinds of drag-and-drop events, the next section
covers how to start drag operations and how to listen for drag-and-drop events.

22.5 Starting drag operations
The drag operation is started when a source view calls its startDrag() method, typically as a response to a long press by the user. In response to this action, you’ll typically
create clip data and related metadata for the data to be moved. You’ll also create the
shadow builder. The following listing shows how to set up for the view’s startDrag()
method.
Listing 22.2

Starting a view drag operation

private String[] mListItems = new String[] {
"Mobility Weblog",
"TechCrunch",
"Manning Books"};
private String[] mListItemsUrls = new String[] {
"http://mobilityweblog.com",
"http://www.TechCrunch.com",
"http://www.manning.com/"};
...
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

Set list view
item longclick listener

C

B

Get source view
ListView lv = getListView();
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView av, View v,
int pos, long id) {
final String title = (String) ((TextView) v).getText();
ClipData data = ClipData.newPlainText(title,
mListItemsUrls[pos]);
DragShadowBuilder shadowBuilder = new MyDragShadowBuilder(v);
v.startDrag(data, shadowBuilder, v, 0);
Start drag
return true;
operation
}
});

D

...
}

This example listens for long presses and starts the drag operation. We define an array
that contains the list of URLs that correspond to the data that can be selected by the