1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 
20 import android.annotation.StringRes;
21 import android.graphics.Rect;
22 
23 /**
24  * Represents a contextual mode of the user interface. Action modes can be used to provide
25  * alternative interaction modes and replace parts of the normal UI until finished.
26  * Examples of good action modes include text selection and contextual actions.
27  * <div class="special reference">
28  * <h3>Developer Guides</h3>
29  * <p>For information about how to provide contextual actions with {@code ActionMode},
30  * read the <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Menus</a>
31  * developer guide.</p>
32  * </div>
33  */
34 public abstract class ActionMode {
35 
36     /**
37      * The action mode is treated as a Primary mode. This is the default.
38      * Use with {@link #setType}.
39      */
40     public static final int TYPE_PRIMARY = 0;
41     /**
42      * The action mode is treated as a Floating Toolbar.
43      * Use with {@link #setType}.
44      */
45     public static final int TYPE_FLOATING = 1;
46 
47     /**
48      * Default value to hide the action mode for
49      * {@link ViewConfiguration#getDefaultActionModeHideDuration()}.
50      */
51     public static final int DEFAULT_HIDE_DURATION = -1;
52 
53     private Object mTag;
54     private boolean mTitleOptionalHint;
55     private int mType = TYPE_PRIMARY;
56 
57     /**
58      * Set a tag object associated with this ActionMode.
59      *
60      * <p>Like the tag available to views, this allows applications to associate arbitrary
61      * data with an ActionMode for later reference.
62      *
63      * @param tag Tag to associate with this ActionMode
64      *
65      * @see #getTag()
66      */
setTag(Object tag)67     public void setTag(Object tag) {
68         mTag = tag;
69     }
70 
71     /**
72      * Retrieve the tag object associated with this ActionMode.
73      *
74      * <p>Like the tag available to views, this allows applications to associate arbitrary
75      * data with an ActionMode for later reference.
76      *
77      * @return Tag associated with this ActionMode
78      *
79      * @see #setTag(Object)
80      */
getTag()81     public Object getTag() {
82         return mTag;
83     }
84 
85     /**
86      * Set the title of the action mode. This method will have no visible effect if
87      * a custom view has been set.
88      *
89      * @param title Title string to set
90      *
91      * @see #setTitle(int)
92      * @see #setCustomView(View)
93      */
setTitle(CharSequence title)94     public abstract void setTitle(CharSequence title);
95 
96     /**
97      * Set the title of the action mode. This method will have no visible effect if
98      * a custom view has been set.
99      *
100      * @param resId Resource ID of a string to set as the title
101      *
102      * @see #setTitle(CharSequence)
103      * @see #setCustomView(View)
104      */
setTitle(@tringRes int resId)105     public abstract void setTitle(@StringRes int resId);
106 
107     /**
108      * Set the subtitle of the action mode. This method will have no visible effect if
109      * a custom view has been set.
110      *
111      * @param subtitle Subtitle string to set
112      *
113      * @see #setSubtitle(int)
114      * @see #setCustomView(View)
115      */
setSubtitle(CharSequence subtitle)116     public abstract void setSubtitle(CharSequence subtitle);
117 
118     /**
119      * Set the subtitle of the action mode. This method will have no visible effect if
120      * a custom view has been set.
121      *
122      * @param resId Resource ID of a string to set as the subtitle
123      *
124      * @see #setSubtitle(CharSequence)
125      * @see #setCustomView(View)
126      */
setSubtitle(@tringRes int resId)127     public abstract void setSubtitle(@StringRes int resId);
128 
129     /**
130      * Set whether or not the title/subtitle display for this action mode
131      * is optional.
132      *
133      * <p>In many cases the supplied title for an action mode is merely
134      * meant to add context and is not strictly required for the action
135      * mode to be useful. If the title is optional, the system may choose
136      * to hide the title entirely rather than truncate it due to a lack
137      * of available space.</p>
138      *
139      * <p>Note that this is merely a hint; the underlying implementation
140      * may choose to ignore this setting under some circumstances.</p>
141      *
142      * @param titleOptional true if the title only presents optional information.
143      */
setTitleOptionalHint(boolean titleOptional)144     public void setTitleOptionalHint(boolean titleOptional) {
145         mTitleOptionalHint = titleOptional;
146     }
147 
148     /**
149      * @return true if this action mode has been given a hint to consider the
150      *         title/subtitle display to be optional.
151      *
152      * @see #setTitleOptionalHint(boolean)
153      * @see #isTitleOptional()
154      */
getTitleOptionalHint()155     public boolean getTitleOptionalHint() {
156         return mTitleOptionalHint;
157     }
158 
159     /**
160      * @return true if this action mode considers the title and subtitle fields
161      *         as optional. Optional titles may not be displayed to the user.
162      */
isTitleOptional()163     public boolean isTitleOptional() {
164         return false;
165     }
166 
167     /**
168      * Set a custom view for this action mode. The custom view will take the place of
169      * the title and subtitle. Useful for things like search boxes.
170      *
171      * @param view Custom view to use in place of the title/subtitle.
172      *
173      * @see #setTitle(CharSequence)
174      * @see #setSubtitle(CharSequence)
175      */
setCustomView(View view)176     public abstract void setCustomView(View view);
177 
178     /**
179      * Set a type for this action mode. This will affect how the system renders the action mode if
180      * it has to.
181      *
182      * @param type One of {@link #TYPE_PRIMARY} or {@link #TYPE_FLOATING}.
183      */
setType(int type)184     public void setType(int type) {
185         mType = type;
186     }
187 
188     /**
189      * Returns the type for this action mode.
190      *
191      * @return One of {@link #TYPE_PRIMARY} or {@link #TYPE_FLOATING}.
192      */
getType()193     public int getType() {
194         return mType;
195     }
196 
197     /**
198      * Invalidate the action mode and refresh menu content. The mode's
199      * {@link ActionMode.Callback} will have its
200      * {@link Callback#onPrepareActionMode(ActionMode, Menu)} method called.
201      * If it returns true the menu will be scanned for updated content and any relevant changes
202      * will be reflected to the user.
203      */
invalidate()204     public abstract void invalidate();
205 
206     /**
207      * Invalidate the content rect associated to this ActionMode. This only makes sense for
208      * action modes that support dynamic positioning on the screen, and provides a more efficient
209      * way to reposition it without invalidating the whole action mode.
210      *
211      * @see Callback2#onGetContentRect(ActionMode, View, Rect) .
212      */
invalidateContentRect()213     public void invalidateContentRect() {}
214 
215     /**
216      * Hide the action mode view from obstructing the content below for a short duration.
217      * This only makes sense for action modes that support dynamic positioning on the screen.
218      * If this method is called again before the hide duration expires, the later hide call will
219      * cancel the former and then take effect.
220      * NOTE that there is an internal limit to how long the mode can be hidden for. It's typically
221      * about a few seconds.
222      *
223      * @param duration The number of milliseconds to hide for.
224      * @see #DEFAULT_HIDE_DURATION
225      */
hide(long duration)226     public void hide(long duration) {}
227 
228     /**
229      * Finish and close this action mode. The action mode's {@link ActionMode.Callback} will
230      * have its {@link Callback#onDestroyActionMode(ActionMode)} method called.
231      */
finish()232     public abstract void finish();
233 
234     /**
235      * Returns the menu of actions that this action mode presents.
236      * @return The action mode's menu.
237      */
getMenu()238     public abstract Menu getMenu();
239 
240     /**
241      * Returns the current title of this action mode.
242      * @return Title text
243      */
getTitle()244     public abstract CharSequence getTitle();
245 
246     /**
247      * Returns the current subtitle of this action mode.
248      * @return Subtitle text
249      */
getSubtitle()250     public abstract CharSequence getSubtitle();
251 
252     /**
253      * Returns the current custom view for this action mode.
254      * @return The current custom view
255      */
getCustomView()256     public abstract View getCustomView();
257 
258     /**
259      * Returns a {@link MenuInflater} with the ActionMode's context.
260      */
getMenuInflater()261     public abstract MenuInflater getMenuInflater();
262 
263     /**
264      * Called when the window containing the view that started this action mode gains or loses
265      * focus.
266      *
267      * @param hasWindowFocus True if the window containing the view that started this action mode
268      *        now has focus, false otherwise.
269      *
270      */
onWindowFocusChanged(boolean hasWindowFocus)271     public void onWindowFocusChanged(boolean hasWindowFocus) {}
272 
273     /**
274      * Returns whether the UI presenting this action mode can take focus or not.
275      * This is used by internal components within the framework that would otherwise
276      * present an action mode UI that requires focus, such as an EditText as a custom view.
277      *
278      * @return true if the UI used to show this action mode can take focus
279      * @hide Internal use only
280      */
isUiFocusable()281     public boolean isUiFocusable() {
282         return true;
283     }
284 
285     /**
286      * Callback interface for action modes. Supplied to
287      * {@link View#startActionMode(Callback)}, a Callback
288      * configures and handles events raised by a user's interaction with an action mode.
289      *
290      * <p>An action mode's lifecycle is as follows:
291      * <ul>
292      * <li>{@link Callback#onCreateActionMode(ActionMode, Menu)} once on initial
293      * creation</li>
294      * <li>{@link Callback#onPrepareActionMode(ActionMode, Menu)} after creation
295      * and any time the {@link ActionMode} is invalidated</li>
296      * <li>{@link Callback#onActionItemClicked(ActionMode, MenuItem)} any time a
297      * contextual action button is clicked</li>
298      * <li>{@link Callback#onDestroyActionMode(ActionMode)} when the action mode
299      * is closed</li>
300      * </ul>
301      */
302     public interface Callback {
303         /**
304          * Called when action mode is first created. The menu supplied will be used to
305          * generate action buttons for the action mode.
306          *
307          * @param mode ActionMode being created
308          * @param menu Menu used to populate action buttons
309          * @return true if the action mode should be created, false if entering this
310          *              mode should be aborted.
311          */
onCreateActionMode(ActionMode mode, Menu menu)312         public boolean onCreateActionMode(ActionMode mode, Menu menu);
313 
314         /**
315          * Called to refresh an action mode's action menu whenever it is invalidated.
316          *
317          * @param mode ActionMode being prepared
318          * @param menu Menu used to populate action buttons
319          * @return true if the menu or action mode was updated, false otherwise.
320          */
onPrepareActionMode(ActionMode mode, Menu menu)321         public boolean onPrepareActionMode(ActionMode mode, Menu menu);
322 
323         /**
324          * Called to report a user click on an action button.
325          *
326          * @param mode The current ActionMode
327          * @param item The item that was clicked
328          * @return true if this callback handled the event, false if the standard MenuItem
329          *          invocation should continue.
330          */
onActionItemClicked(ActionMode mode, MenuItem item)331         public boolean onActionItemClicked(ActionMode mode, MenuItem item);
332 
333         /**
334          * Called when an action mode is about to be exited and destroyed.
335          *
336          * @param mode The current ActionMode being destroyed
337          */
onDestroyActionMode(ActionMode mode)338         public void onDestroyActionMode(ActionMode mode);
339     }
340 
341     /**
342      * Extension of {@link ActionMode.Callback} to provide content rect information. This is
343      * required for ActionModes with dynamic positioning such as the ones with type
344      * {@link ActionMode#TYPE_FLOATING} to ensure the positioning doesn't obscure app content. If
345      * an app fails to provide a subclass of this class, a default implementation will be used.
346      */
347     public static abstract class Callback2 implements ActionMode.Callback {
348 
349         /**
350          * Called when an ActionMode needs to be positioned on screen, potentially occluding view
351          * content. Note this may be called on a per-frame basis.
352          *
353          * @param mode The ActionMode that requires positioning.
354          * @param view The View that originated the ActionMode, in whose coordinates the Rect should
355          *          be provided.
356          * @param outRect The Rect to be populated with the content position. Use this to specify
357          *          where the content in your app lives within the given view. This will be used
358          *          to avoid occluding the given content Rect with the created ActionMode.
359          */
onGetContentRect(ActionMode mode, View view, Rect outRect)360         public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
361             if (view != null) {
362                 outRect.set(0, 0, view.getWidth(), view.getHeight());
363             } else {
364                 outRect.set(0, 0, 0, 0);
365             }
366         }
367 
368     }
369 }
370