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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 238 public abstract Menu getMenu(); 239 240 /** 241 * Returns the current title of this action mode. 242 * @return Title text 243 */ 244 public abstract CharSequence getTitle(); 245 246 /** 247 * Returns the current subtitle of this action mode. 248 * @return Subtitle text 249 */ 250 public abstract CharSequence getSubtitle(); 251 252 /** 253 * Returns the current custom view for this action mode. 254 * @return The current custom view 255 */ 256 public abstract View getCustomView(); 257 258 /** 259 * Returns a {@link MenuInflater} with the ActionMode's context. 260 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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