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