GuidedAction.java revision 7af424644dc8daae5298a5ca2f655770270366fe
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14package android.support.v17.leanback.widget; 15 16import android.support.v17.leanback.R; 17 18import android.content.Context; 19import android.content.Intent; 20import android.graphics.drawable.Drawable; 21import android.text.InputType; 22import android.util.Log; 23 24/** 25 * A data class which represents an action within a {@link 26 * android.support.v17.leanback.app.GuidedStepFragment}. GuidedActions contain at minimum a title 27 * and a description, and typically also an icon. 28 * <p> 29 * A GuidedAction typically represents a single action a user may take, but may also represent a 30 * possible choice out of a group of mutually exclusive choices (similar to radio buttons), or an 31 * information-only label (in which case the item cannot be clicked). 32 * <p> 33 * GuidedActions may optionally be checked. They may also indicate that they will request further 34 * user input on selection, in which case they will be displayed with a chevron indicator. 35 */ 36public class GuidedAction extends Action { 37 38 private static final String TAG = "GuidedAction"; 39 40 public static final int NO_CHECK_SET = 0; 41 public static final int DEFAULT_CHECK_SET_ID = 1; 42 43 /** 44 * When finishing editing, goes to next action. 45 */ 46 public static final long ACTION_ID_NEXT = -2; 47 /** 48 * When finishing editing, stay on current action. 49 */ 50 public static final long ACTION_ID_CURRENT = -3; 51 52 /** 53 * Id of standard OK action. 54 */ 55 public static final long ACTION_ID_OK = -4; 56 57 /** 58 * Id of standard Cancel action. 59 */ 60 public static final long ACTION_ID_CANCEL = -5; 61 62 /** 63 * Id of standard Finish action. 64 */ 65 public static final long ACTION_ID_FINISH = -6; 66 67 /** 68 * Id of standard Finish action. 69 */ 70 public static final long ACTION_ID_CONTINUE = -7; 71 72 /** 73 * Id of standard Yes action. 74 */ 75 public static final long ACTION_ID_YES = -8; 76 77 /** 78 * Id of standard No action. 79 */ 80 public static final long ACTION_ID_NO = -9; 81 82 /** 83 * Builds a {@link GuidedAction} object. When subclass GuidedAction, you may override this 84 * Builder class and call {@link #applyValues(GuidedAction)}. 85 */ 86 public static class Builder { 87 private long mId; 88 private CharSequence mTitle; 89 private CharSequence mEditTitle; 90 private CharSequence mDescription; 91 private CharSequence mEditDescription; 92 private Drawable mIcon; 93 private boolean mChecked; 94 private boolean mMultilineDescription; 95 private boolean mHasNext; 96 private boolean mInfoOnly; 97 private boolean mEditable = false; 98 private boolean mDescriptionEditable = false; 99 private int mInputType = InputType.TYPE_CLASS_TEXT; 100 private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT; 101 private int mEditInputType = InputType.TYPE_CLASS_TEXT; 102 private int mDescriptionEditInputType = InputType.TYPE_CLASS_TEXT; 103 private int mCheckSetId = NO_CHECK_SET; 104 private boolean mEnabled = true; 105 private boolean mFocusable = true; 106 private Intent mIntent; 107 108 /** 109 * Builds the GuidedAction corresponding to this Builder. 110 * @return the GuidedAction as configured through this Builder. 111 */ 112 public final GuidedAction build() { 113 GuidedAction action = new GuidedAction(); 114 applyValues(action); 115 return action; 116 } 117 118 /** 119 * Subclass Builder may call this function to apply values. 120 * @param action GuidedAction to apply Builder values. 121 */ 122 protected final void applyValues(GuidedAction action) { 123 // Base Action values 124 action.setId(mId); 125 action.setLabel1(mTitle); 126 action.setEditTitle(mEditTitle); 127 action.setLabel2(mDescription); 128 action.setEditDescription(mEditDescription); 129 action.setIcon(mIcon); 130 131 // Subclass values 132 action.mIntent = mIntent; 133 action.mEditable = mEditable; 134 action.mDescriptionEditable = mDescriptionEditable; 135 action.mInputType = mInputType; 136 action.mDescriptionInputType = mDescriptionInputType; 137 action.mEditInputType = mEditInputType; 138 action.mDescriptionEditInputType = mDescriptionEditInputType; 139 action.mChecked = mChecked; 140 action.mCheckSetId = mCheckSetId; 141 action.mMultilineDescription = mMultilineDescription; 142 action.mHasNext = mHasNext; 143 action.mInfoOnly = mInfoOnly; 144 action.mEnabled = mEnabled; 145 action.mFocusable = mFocusable; 146 } 147 148 /** 149 * Construct a standard "OK" action with {@link GuidedAction#ACTION_ID_OK}. 150 * @param context Context for loading action title. 151 * @return The same Builder object. 152 */ 153 public Builder constructOK(Context context) { 154 mId = ACTION_ID_OK; 155 mTitle = context.getString(android.R.string.ok); 156 return this; 157 } 158 159 /** 160 * Construct a standard "Cancel" action with {@link GuidedAction#ACTION_ID_CANCEL}. 161 * @param context Context for loading action title. 162 * @return The same Builder object. 163 */ 164 public Builder constructCancel(Context context) { 165 mId = ACTION_ID_CANCEL; 166 mTitle = context.getString(android.R.string.cancel); 167 return this; 168 } 169 170 /** 171 * Construct a standard "Finish" action with {@link GuidedAction#ACTION_ID_FINISH}. 172 * @param context Context for loading action title. 173 * @return The same Builder object. 174 */ 175 public Builder constructFinish(Context context) { 176 mId = ACTION_ID_FINISH; 177 mTitle = context.getString(R.string.lb_guidedaction_finish_title); 178 return this; 179 } 180 181 /** 182 * Construct a standard "Continue" action with {@link GuidedAction#ACTION_ID_CONTINUE}. 183 * @param context Context for loading action title. 184 * @return The same Builder object. 185 */ 186 public Builder constructContinue(Context context) { 187 mId = ACTION_ID_CONTINUE; 188 mHasNext = true; 189 mTitle = context.getString(R.string.lb_guidedaction_continue_title); 190 return this; 191 } 192 193 /** 194 * Construct a standard "Yes" action with {@link GuidedAction#ACTION_ID_YES}. 195 * @param context Context for loading action title. 196 * @return The same Builder object. 197 */ 198 public Builder constructYes(Context context) { 199 mId = ACTION_ID_YES; 200 mTitle = context.getString(android.R.string.yes); 201 return this; 202 } 203 204 /** 205 * Construct a standard "No" action with {@link GuidedAction#ACTION_ID_NO}. 206 * @param context Context for loading action title. 207 * @return The same Builder object. 208 */ 209 public Builder constructNo(Context context) { 210 mId = ACTION_ID_NO; 211 mTitle = context.getString(android.R.string.no); 212 return this; 213 } 214 215 /** 216 * Sets the ID associated with this action. The ID can be any value the client wishes; 217 * it is typically used to determine what to do when an action is clicked. 218 * @param id The ID to associate with this action. 219 */ 220 public Builder id(long id) { 221 mId = id; 222 return this; 223 } 224 225 /** 226 * Sets the title for this action. The title is typically a short string indicating the 227 * action to be taken on click, e.g. "Continue" or "Cancel". 228 * @param title The title for this action. 229 */ 230 public Builder title(CharSequence title) { 231 mTitle = title; 232 return this; 233 } 234 235 /** 236 * Sets the optional title text to edit. When TextView is activated, the edit title 237 * replaces the string of title. 238 */ 239 public Builder editTitle(CharSequence editTitle) { 240 mEditTitle = editTitle; 241 return this; 242 } 243 244 /** 245 * Sets the description for this action. The description is typically a longer string 246 * providing extra information on what the action will do. 247 * @param description The description for this action. 248 */ 249 public Builder description(CharSequence description) { 250 mDescription = description; 251 return this; 252 } 253 254 /** 255 * Sets the optional description text to edit. When TextView is activated, the edit 256 * description replaces the string of description. 257 * @param description The description to edit for this action. 258 */ 259 public Builder editDescription(CharSequence description) { 260 mEditDescription = description; 261 return this; 262 } 263 264 /** 265 * Sets the intent associated with this action. Clients would typically fire this intent 266 * directly when the action is clicked. 267 * @param intent The intent associated with this action. 268 */ 269 public Builder intent(Intent intent) { 270 mIntent = intent; 271 return this; 272 } 273 274 /** 275 * Sets the action's icon drawable. 276 * @param icon The drawable for the icon associated with this action. 277 */ 278 public Builder icon(Drawable icon) { 279 mIcon = icon; 280 return this; 281 } 282 283 /** 284 * Sets the action's icon drawable by retrieving it by resource ID from the specified 285 * context. This is a convenience function that simply looks up the drawable and calls 286 * {@link #icon}. 287 * @param iconResourceId The resource ID for the icon associated with this action. 288 * @param context The context whose resource ID should be retrieved. 289 */ 290 public Builder iconResourceId(int iconResourceId, Context context) { 291 return icon(context.getResources().getDrawable(iconResourceId)); 292 } 293 294 /** 295 * Indicates whether this action is editable. Note: Editable actions cannot also be 296 * checked, or belong to a check set. 297 * @param editable Whether this action is editable. 298 */ 299 public Builder editable(boolean editable) { 300 mEditable = editable; 301 if (mChecked || mCheckSetId != NO_CHECK_SET) { 302 throw new IllegalArgumentException("Editable actions cannot also be checked"); 303 } 304 return this; 305 } 306 307 /** 308 * Indicates whether this action's description is editable 309 * @param editable Whether this action description is editable. 310 */ 311 public Builder descriptionEditable(boolean editable) { 312 mDescriptionEditable = editable; 313 if (mChecked || mCheckSetId != NO_CHECK_SET) { 314 throw new IllegalArgumentException("Editable actions cannot also be checked"); 315 } 316 return this; 317 } 318 319 /** 320 * Sets {@link InputType} of this action title not in editing. 321 * 322 * @param inputType InputType for the action title not in editing. 323 */ 324 public Builder inputType(int inputType) { 325 mInputType = inputType; 326 return this; 327 } 328 329 /** 330 * Sets {@link InputType} of this action description not in editing. 331 * 332 * @param inputType InputType for the action description not in editing. 333 */ 334 public Builder descriptionInputType(int inputType) { 335 mDescriptionInputType = inputType; 336 return this; 337 } 338 339 340 /** 341 * Sets {@link InputType} of this action title in editing. 342 * 343 * @param inputType InputType for the action title in editing. 344 */ 345 public Builder editInputType(int inputType) { 346 mEditInputType = inputType; 347 return this; 348 } 349 350 /** 351 * Sets {@link InputType} of this action description in editing. 352 * 353 * @param inputType InputType for the action description in editing. 354 */ 355 public Builder descriptionEditInputType(int inputType) { 356 mDescriptionEditInputType = inputType; 357 return this; 358 } 359 360 361 /** 362 * Indicates whether this action is initially checked. 363 * @param checked Whether this action is checked. 364 */ 365 public Builder checked(boolean checked) { 366 mChecked = checked; 367 if (mEditable || mDescriptionEditable) { 368 throw new IllegalArgumentException("Editable actions cannot also be checked"); 369 } 370 return this; 371 } 372 373 /** 374 * Indicates whether this action is part of a single-select group similar to radio buttons. 375 * When one item in a check set is checked, all others with the same check set ID will be 376 * unchecked automatically. 377 * @param checkSetId The check set ID, or {@link #NO_CHECK_SET) to indicate no check set. 378 */ 379 public Builder checkSetId(int checkSetId) { 380 mCheckSetId = checkSetId; 381 if (mEditable || mDescriptionEditable) { 382 throw new IllegalArgumentException("Editable actions cannot also be in check sets"); 383 } 384 return this; 385 } 386 387 /** 388 * Indicates whether the title and description are long, and should be displayed 389 * appropriately. 390 * @param multilineDescription Whether this action has a multiline description. 391 */ 392 public Builder multilineDescription(boolean multilineDescription) { 393 mMultilineDescription = multilineDescription; 394 return this; 395 } 396 397 /** 398 * Indicates whether this action has a next state and should display a chevron. 399 * @param hasNext Whether this action has a next state. 400 */ 401 public Builder hasNext(boolean hasNext) { 402 mHasNext = hasNext; 403 return this; 404 } 405 406 /** 407 * Indicates whether this action is for information purposes only and cannot be clicked. 408 * @param infoOnly Whether this action has a next state. 409 */ 410 public Builder infoOnly(boolean infoOnly) { 411 mInfoOnly = infoOnly; 412 return this; 413 } 414 415 /** 416 * Indicates whether this action is enabled. If not enabled, an action cannot be clicked. 417 * @param enabled Whether the action is enabled. 418 */ 419 public Builder enabled(boolean enabled) { 420 mEnabled = enabled; 421 return this; 422 } 423 424 /** 425 * Indicates whether this action can take focus. 426 * @param focusable 427 * @return The same Builder object. 428 */ 429 public Builder focusable(boolean focusable) { 430 mFocusable = focusable; 431 return this; 432 } 433 } 434 435 private CharSequence mEditTitle; 436 private CharSequence mEditDescription; 437 private boolean mEditable; 438 private boolean mDescriptionEditable; 439 private int mInputType; 440 private int mDescriptionInputType; 441 private int mEditInputType; 442 private int mDescriptionEditInputType; 443 private boolean mMultilineDescription; 444 private boolean mHasNext; 445 private boolean mChecked; 446 private boolean mInfoOnly; 447 private int mCheckSetId; 448 private boolean mEnabled; 449 private boolean mFocusable; 450 451 private Intent mIntent; 452 453 protected GuidedAction() { 454 super(0); 455 } 456 457 /** 458 * Returns the title of this action. 459 * @return The title set when this action was built. 460 */ 461 public CharSequence getTitle() { 462 return getLabel1(); 463 } 464 465 /** 466 * Sets the title of this action. 467 * @param title The title set when this action was built. 468 */ 469 public void setTitle(CharSequence title) { 470 setLabel1(title); 471 } 472 473 /** 474 * Returns the optional title text to edit. When not null, it is being edited instead of 475 * {@link #getTitle()}. 476 * @return Optional title text to edit instead of {@link #getTitle()}. 477 */ 478 public CharSequence getEditTitle() { 479 return mEditTitle; 480 } 481 482 /** 483 * Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}. 484 * @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}. 485 */ 486 public void setEditTitle(CharSequence editTitle) { 487 mEditTitle = editTitle; 488 } 489 490 /** 491 * Returns the optional description text to edit. When not null, it is being edited instead of 492 * {@link #getDescription()}. 493 * @return Optional description text to edit instead of {@link #getDescription()}. 494 */ 495 public CharSequence getEditDescription() { 496 return mEditDescription; 497 } 498 499 /** 500 * Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}. 501 * @param editDescription Optional description text to edit instead of 502 * {@link #setDescription(CharSequence)}. 503 */ 504 public void setEditDescription(CharSequence editDescription) { 505 mEditDescription = editDescription; 506 } 507 508 /** 509 * Returns true if {@link #getEditTitle()} is not null. When true, the {@link #getEditTitle()} 510 * is being edited instead of {@link #getTitle()}. 511 * @return true if {@link #getEditTitle()} is not null. 512 */ 513 public boolean isEditTitleUsed() { 514 return mEditTitle != null; 515 } 516 517 /** 518 * Returns the description of this action. 519 * @return The description of this action. 520 */ 521 public CharSequence getDescription() { 522 return getLabel2(); 523 } 524 525 /** 526 * Sets the description of this action. 527 * @param description The description of the action. 528 */ 529 public void setDescription(CharSequence description) { 530 setLabel2(description); 531 } 532 533 /** 534 * Returns the intent associated with this action. 535 * @return The intent set when this action was built. 536 */ 537 public Intent getIntent() { 538 return mIntent; 539 } 540 541 /** 542 * Returns whether this action is editable. 543 * @return true if the action is editable, false otherwise. 544 */ 545 public boolean isEditable() { 546 return mEditable; 547 } 548 549 /** 550 * Returns whether this action description is editable. 551 * @return true if the action description is editable, false otherwise. 552 */ 553 public boolean isDescriptionEditable() { 554 return mDescriptionEditable; 555 } 556 557 /** 558 * Returns InputType of action title in editing; only valid when {@link #isEditable()} is true. 559 * @return InputType of action title in editing. 560 */ 561 public int getEditInputType() { 562 return mEditInputType; 563 } 564 565 /** 566 * Returns InputType of action description in editing; only valid when 567 * {@link #isDescriptionEditable()} is true. 568 * @return InputType of action description in editing. 569 */ 570 public int getDescriptionEditInputType() { 571 return mDescriptionEditInputType; 572 } 573 574 /** 575 * Returns InputType of action title not in editing. 576 * @return InputType of action title not in editing. 577 */ 578 public int getInputType() { 579 return mInputType; 580 } 581 582 /** 583 * Returns InputType of action description not in editing. 584 * @return InputType of action description not in editing. 585 */ 586 public int getDescriptionInputType() { 587 return mDescriptionInputType; 588 } 589 590 /** 591 * Returns whether this action is checked. 592 * @return true if the action is currently checked, false otherwise. 593 */ 594 public boolean isChecked() { 595 return mChecked; 596 } 597 598 /** 599 * Sets whether this action is checked. 600 * @param checked Whether this action should be checked. 601 */ 602 public void setChecked(boolean checked) { 603 mChecked = checked; 604 } 605 606 /** 607 * Returns the check set id this action is a part of. All actions in the 608 * same list with the same check set id are considered linked. When one 609 * of the actions within that set is selected, that action becomes 610 * checked, while all the other actions become unchecked. 611 * 612 * @return an integer representing the check set this action is a part of, or 613 * {@link #NO_CHECK_SET} if this action isn't a part of a check set. 614 */ 615 public int getCheckSetId() { 616 return mCheckSetId; 617 } 618 619 /** 620 * Returns whether this action is has a multiline description. 621 * @return true if the action was constructed as having a multiline description, false 622 * otherwise. 623 */ 624 public boolean hasMultilineDescription() { 625 return mMultilineDescription; 626 } 627 628 /** 629 * Returns whether this action is enabled. 630 * @return true if the action is currently enabled, false otherwise. 631 */ 632 public boolean isEnabled() { 633 return mEnabled; 634 } 635 636 /** 637 * Sets whether this action is enabled. 638 * @param enabled Whether this action should be enabled. 639 */ 640 public void setEnabled(boolean enabled) { 641 mEnabled = enabled; 642 } 643 644 /** 645 * Returns whether this action is focusable. 646 * @return true if the action is currently focusable, false otherwise. 647 */ 648 public boolean isFocusable() { 649 return mFocusable; 650 } 651 652 /** 653 * Sets whether this action is focusable. 654 * @param focusable Whether this action should be focusable. 655 */ 656 public void setFocusable(boolean focusable) { 657 mFocusable = focusable; 658 } 659 660 /** 661 * Returns whether this action will request further user input when selected, such as showing 662 * another GuidedStepFragment or launching a new activity. Configured during construction. 663 * @return true if the action will request further user input when selected, false otherwise. 664 */ 665 public boolean hasNext() { 666 return mHasNext; 667 } 668 669 /** 670 * Returns whether the action will only display information and is thus not clickable. If both 671 * this and {@link #hasNext()} are true, infoOnly takes precedence. The default is false. For 672 * example, this might represent e.g. the amount of storage a document uses, or the cost of an 673 * app. 674 * @return true if will only display information, false otherwise. 675 */ 676 public boolean infoOnly() { 677 return mInfoOnly; 678 } 679 680} 681