blob: 888ba0b168eb6e06c2a3157741b75882667ab9ae [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package androidx.leanback.widget;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.InputType;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.leanback.R;
import java.util.List;
/**
* A data class which represents an action within a {@link
* androidx.leanback.app.GuidedStepFragment}. GuidedActions contain at minimum a title
* and a description, and typically also an icon.
* <p>
* A GuidedAction typically represents a single action a user may take, but may also represent a
* possible choice out of a group of mutually exclusive choices (similar to radio buttons), or an
* information-only label (in which case the item cannot be clicked).
* <p>
* GuidedActions may optionally be checked. They may also indicate that they will request further
* user input on selection, in which case they will be displayed with a chevron indicator.
* <p>
* GuidedAction recommends to use {@link Builder}. When application subclass GuidedAction, it
* can subclass {@link BuilderBase}, implement its own builder() method where it should
* call {@link BuilderBase#applyValues(GuidedAction)}.
*/
public class GuidedAction extends Action {
private static final String TAG = "GuidedAction";
/**
* Special check set Id that is neither checkbox nor radio.
*/
public static final int NO_CHECK_SET = 0;
/**
* Default checkset Id for radio.
*/
public static final int DEFAULT_CHECK_SET_ID = 1;
/**
* Checkset Id for checkbox.
*/
public static final int CHECKBOX_CHECK_SET_ID = -1;
/**
* When finishing editing, goes to next action.
*/
public static final long ACTION_ID_NEXT = -2;
/**
* When finishing editing, stay on current action.
*/
public static final long ACTION_ID_CURRENT = -3;
/**
* Id of standard OK action.
*/
public static final long ACTION_ID_OK = -4;
/**
* Id of standard Cancel action.
*/
public static final long ACTION_ID_CANCEL = -5;
/**
* Id of standard Finish action.
*/
public static final long ACTION_ID_FINISH = -6;
/**
* Id of standard Finish action.
*/
public static final long ACTION_ID_CONTINUE = -7;
/**
* Id of standard Yes action.
*/
public static final long ACTION_ID_YES = -8;
/**
* Id of standard No action.
*/
public static final long ACTION_ID_NO = -9;
static final int EDITING_NONE = 0;
static final int EDITING_TITLE = 1;
static final int EDITING_DESCRIPTION = 2;
static final int EDITING_ACTIVATOR_VIEW = 3;
/**
* Base builder class to build a {@link GuidedAction} object. When subclass GuidedAction, you
* can override this BuilderBase class, implements your build() method which should call
* {@link #applyValues(GuidedAction)}. When using GuidedAction directly, use {@link Builder}.
*/
public abstract static class BuilderBase<B extends BuilderBase> {
private Context mContext;
private long mId;
private CharSequence mTitle;
private CharSequence mEditTitle;
private CharSequence mDescription;
private CharSequence mEditDescription;
private String[] mAutofillHints;
private Drawable mIcon;
/**
* The mActionFlags holds various action states such as whether title or description are
* editable, or the action is focusable.
*
*/
private int mActionFlags;
private int mEditable = EDITING_NONE;
private int mInputType = InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
private int mEditInputType = InputType.TYPE_CLASS_TEXT;
private int mDescriptionEditInputType = InputType.TYPE_CLASS_TEXT;
private int mCheckSetId = NO_CHECK_SET;
private List<GuidedAction> mSubActions;
private Intent mIntent;
/**
* Creates a BuilderBase for GuidedAction or its subclass.
* @param context Context object used to build the GuidedAction.
*/
public BuilderBase(Context context) {
mContext = context;
mActionFlags = PF_ENABLED | PF_FOCUSABLE | PF_AUTORESTORE;
}
/**
* Returns Context of this Builder.
* @return Context of this Builder.
*/
public Context getContext() {
return mContext;
}
private void setFlags(int flag, int mask) {
mActionFlags = (mActionFlags & ~mask) | (flag & mask);
}
/**
* Subclass of BuilderBase should call this function to apply values.
* @param action GuidedAction to apply BuilderBase values.
*/
protected final void applyValues(GuidedAction action) {
// Base Action values
action.setId(mId);
action.setLabel1(mTitle);
action.setEditTitle(mEditTitle);
action.setLabel2(mDescription);
action.setEditDescription(mEditDescription);
action.setIcon(mIcon);
// Subclass values
action.mIntent = mIntent;
action.mEditable = mEditable;
action.mInputType = mInputType;
action.mDescriptionInputType = mDescriptionInputType;
action.mAutofillHints = mAutofillHints;
action.mEditInputType = mEditInputType;
action.mDescriptionEditInputType = mDescriptionEditInputType;
action.mActionFlags = mActionFlags;
action.mCheckSetId = mCheckSetId;
action.mSubActions = mSubActions;
}
/**
* Construct a clickable action with associated id and auto assign pre-defined title for the
* action. If the id is not supported, the method simply does nothing.
* @param id One of {@link GuidedAction#ACTION_ID_OK} {@link GuidedAction#ACTION_ID_CANCEL}
* {@link GuidedAction#ACTION_ID_FINISH} {@link GuidedAction#ACTION_ID_CONTINUE}
* {@link GuidedAction#ACTION_ID_YES} {@link GuidedAction#ACTION_ID_NO}.
* @return The same BuilderBase object.
*/
public B clickAction(long id) {
if (id == ACTION_ID_OK) {
mId = ACTION_ID_OK;
mTitle = mContext.getString(android.R.string.ok);
} else if (id == ACTION_ID_CANCEL) {
mId = ACTION_ID_CANCEL;
mTitle = mContext.getString(android.R.string.cancel);
} else if (id == ACTION_ID_FINISH) {
mId = ACTION_ID_FINISH;
mTitle = mContext.getString(R.string.lb_guidedaction_finish_title);
} else if (id == ACTION_ID_CONTINUE) {
mId = ACTION_ID_CONTINUE;
mTitle = mContext.getString(R.string.lb_guidedaction_continue_title);
} else if (id == ACTION_ID_YES) {
mId = ACTION_ID_YES;
mTitle = mContext.getString(android.R.string.ok);
} else if (id == ACTION_ID_NO) {
mId = ACTION_ID_NO;
mTitle = mContext.getString(android.R.string.cancel);
}
return (B) this;
}
/**
* Sets the ID associated with this action. The ID can be any value the client wishes;
* it is typically used to determine what to do when an action is clicked.
* @param id The ID to associate with this action.
*/
public B id(long id) {
mId = id;
return (B) this;
}
/**
* Sets the title for this action. The title is typically a short string indicating the
* action to be taken on click, e.g. "Continue" or "Cancel".
* @param title The title for this action.
*/
public B title(CharSequence title) {
mTitle = title;
return (B) this;
}
/**
* Sets the title for this action. The title is typically a short string indicating the
* action to be taken on click, e.g. "Continue" or "Cancel".
* @param titleResourceId The resource id of title for this action.
*/
public B title(@StringRes int titleResourceId) {
mTitle = getContext().getString(titleResourceId);
return (B) this;
}
/**
* Sets the optional title text to edit. When TextView is activated, the edit title
* replaces the string of title.
* @param editTitle The optional title text to edit when TextView is activated.
*/
public B editTitle(CharSequence editTitle) {
mEditTitle = editTitle;
return (B) this;
}
/**
* Sets the optional title text to edit. When TextView is activated, the edit title
* replaces the string of title.
* @param editTitleResourceId String resource id of the optional title text to edit when
* TextView is activated.
*/
public B editTitle(@StringRes int editTitleResourceId) {
mEditTitle = getContext().getString(editTitleResourceId);
return (B) this;
}
/**
* Sets the description for this action. The description is typically a longer string
* providing extra information on what the action will do.
* @param description The description for this action.
*/
public B description(CharSequence description) {
mDescription = description;
return (B) this;
}
/**
* Sets the description for this action. The description is typically a longer string
* providing extra information on what the action will do.
* @param descriptionResourceId String resource id of the description for this action.
*/
public B description(@StringRes int descriptionResourceId) {
mDescription = getContext().getString(descriptionResourceId);
return (B) this;
}
/**
* Sets the optional description text to edit. When TextView is activated, the edit
* description replaces the string of description.
* @param description The description to edit for this action.
*/
public B editDescription(CharSequence description) {
mEditDescription = description;
return (B) this;
}
/**
* Sets the optional description text to edit. When TextView is activated, the edit
* description replaces the string of description.
* @param descriptionResourceId String resource id of the description to edit for this
* action.
*/
public B editDescription(@StringRes int descriptionResourceId) {
mEditDescription = getContext().getString(descriptionResourceId);
return (B) this;
}
/**
* Sets the intent associated with this action. Clients would typically fire this intent
* directly when the action is clicked.
* @param intent The intent associated with this action.
*/
public B intent(Intent intent) {
mIntent = intent;
return (B) this;
}
/**
* Sets the action's icon drawable.
* @param icon The drawable for the icon associated with this action.
*/
public B icon(Drawable icon) {
mIcon = icon;
return (B) this;
}
/**
* Sets the action's icon drawable by retrieving it by resource ID from the specified
* context. This is a convenience function that simply looks up the drawable and calls
* {@link #icon(Drawable)}.
* @param iconResourceId The resource ID for the icon associated with this action.
* @param context The context whose resource ID should be retrieved.
* @deprecated Use {@link #icon(int)}.
*/
@Deprecated
public B iconResourceId(@DrawableRes int iconResourceId, Context context) {
return icon(ContextCompat.getDrawable(context, iconResourceId));
}
/**
* Sets the action's icon drawable by retrieving it by resource ID from Builder's
* context. This is a convenience function that simply looks up the drawable and calls
* {@link #icon(Drawable)}.
* @param iconResourceId The resource ID for the icon associated with this action.
*/
public B icon(@DrawableRes int iconResourceId) {
return icon(ContextCompat.getDrawable(getContext(), iconResourceId));
}
/**
* Indicates whether this action title is editable. Note: Editable actions cannot also be
* checked, or belong to a check set.
* @param editable Whether this action is editable.
*/
public B editable(boolean editable) {
if (!editable) {
if (mEditable == EDITING_TITLE) {
mEditable = EDITING_NONE;
}
return (B) this;
}
mEditable = EDITING_TITLE;
if (isChecked() || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return (B) this;
}
/**
* Indicates whether this action's description is editable
* @param editable Whether this action description is editable.
*/
public B descriptionEditable(boolean editable) {
if (!editable) {
if (mEditable == EDITING_DESCRIPTION) {
mEditable = EDITING_NONE;
}
return (B) this;
}
mEditable = EDITING_DESCRIPTION;
if (isChecked() || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return (B) this;
}
/**
* Indicates whether this action has a view can be activated to edit, e.g. a DatePicker.
* @param editable Whether this action has view can be activated to edit.
*/
public B hasEditableActivatorView(boolean editable) {
if (!editable) {
if (mEditable == EDITING_ACTIVATOR_VIEW) {
mEditable = EDITING_NONE;
}
return (B) this;
}
mEditable = EDITING_ACTIVATOR_VIEW;
if (isChecked() || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return (B) this;
}
/**
* Sets {@link InputType} of this action title not in editing.
*
* @param inputType InputType for the action title not in editing.
*/
public B inputType(int inputType) {
mInputType = inputType;
return (B) this;
}
/**
* Sets {@link InputType} of this action description not in editing.
*
* @param inputType InputType for the action description not in editing.
*/
public B descriptionInputType(int inputType) {
mDescriptionInputType = inputType;
return (B) this;
}
/**
* Sets {@link InputType} of this action title in editing.
*
* @param inputType InputType for the action title in editing.
*/
public B editInputType(int inputType) {
mEditInputType = inputType;
return (B) this;
}
/**
* Sets {@link InputType} of this action description in editing.
*
* @param inputType InputType for the action description in editing.
*/
public B descriptionEditInputType(int inputType) {
mDescriptionEditInputType = inputType;
return (B) this;
}
private boolean isChecked() {
return (mActionFlags & PF_CHECKED) == PF_CHECKED;
}
/**
* Indicates whether this action is initially checked.
* @param checked Whether this action is checked.
*/
public B checked(boolean checked) {
setFlags(checked ? PF_CHECKED : 0, PF_CHECKED);
if (mEditable != EDITING_NONE) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return (B) this;
}
/**
* Indicates whether this action is part of a single-select group similar to radio buttons
* or this action is a checkbox. When one item in a check set is checked, all others with
* the same check set ID will be checked automatically.
* @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
* radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
*/
public B checkSetId(int checkSetId) {
mCheckSetId = checkSetId;
if (mEditable != EDITING_NONE) {
throw new IllegalArgumentException("Editable actions cannot also be in check sets");
}
return (B) this;
}
/**
* Indicates whether the title and description are long, and should be displayed
* appropriately.
* @param multilineDescription Whether this action has a multiline description.
*/
public B multilineDescription(boolean multilineDescription) {
setFlags(multilineDescription ? PF_MULTI_LINE_DESCRIPTION : 0,
PF_MULTI_LINE_DESCRIPTION);
return (B) this;
}
/**
* Indicates whether this action has a next state and should display a chevron.
* @param hasNext Whether this action has a next state.
*/
public B hasNext(boolean hasNext) {
setFlags(hasNext ? PF_HAS_NEXT : 0, PF_HAS_NEXT);
return (B) this;
}
/**
* Indicates whether this action is for information purposes only and cannot be clicked.
* @param infoOnly Whether this action has a next state.
*/
public B infoOnly(boolean infoOnly) {
setFlags(infoOnly ? PF_INFO_ONLY : 0, PF_INFO_ONLY);
return (B) this;
}
/**
* Indicates whether this action is enabled. If not enabled, an action cannot be clicked.
* @param enabled Whether the action is enabled.
*/
public B enabled(boolean enabled) {
setFlags(enabled ? PF_ENABLED : 0, PF_ENABLED);
return (B) this;
}
/**
* Indicates whether this action can take focus.
* @param focusable
* @return The same BuilderBase object.
*/
public B focusable(boolean focusable) {
setFlags(focusable ? PF_FOCUSABLE : 0, PF_FOCUSABLE);
return (B) this;
}
/**
* Sets sub actions list.
* @param subActions
* @return The same BuilderBase object.
*/
public B subActions(List<GuidedAction> subActions) {
mSubActions = subActions;
return (B) this;
}
/**
* Explicitly sets auto restore feature on the GuidedAction. It's by default true.
* @param autoSaveRestoreEnabled True if turn on auto save/restore of GuidedAction content,
* false otherwise.
* @return The same BuilderBase object.
* @see GuidedAction#isAutoSaveRestoreEnabled()
*/
public B autoSaveRestoreEnabled(boolean autoSaveRestoreEnabled) {
setFlags(autoSaveRestoreEnabled ? PF_AUTORESTORE : 0, PF_AUTORESTORE);
return (B) this;
}
/**
* Sets autofill hints. See {@link android.view.View#setAutofillHints}
* @param hints List of hints for autofill.
* @return The same BuilderBase object.
*/
public B autofillHints(String... hints) {
mAutofillHints = hints;
return (B) this;
}
}
/**
* Builds a {@link GuidedAction} object.
*/
public static class Builder extends BuilderBase<Builder> {
/**
* @deprecated Use {@link GuidedAction.Builder#GuidedAction.Builder(Context)}.
*/
@Deprecated
public Builder() {
super(null);
}
/**
* Creates a Builder for GuidedAction.
* @param context Context to build GuidedAction.
*/
public Builder(Context context) {
super(context);
}
/**
* Builds the GuidedAction corresponding to this Builder.
* @return The GuidedAction as configured through this Builder.
*/
public GuidedAction build() {
GuidedAction action = new GuidedAction();
applyValues(action);
return action;
}
}
static final int PF_CHECKED = 0x00000001;
static final int PF_MULTI_LINE_DESCRIPTION = 0x00000002;
static final int PF_HAS_NEXT = 0x00000004;
static final int PF_INFO_ONLY = 0x00000008;
static final int PF_ENABLED = 0x00000010;
static final int PF_FOCUSABLE = 0x00000020;
static final int PF_AUTORESTORE = 0x00000040;
int mActionFlags;
private CharSequence mEditTitle;
private CharSequence mEditDescription;
int mEditable;
int mInputType;
int mDescriptionInputType;
int mEditInputType;
int mDescriptionEditInputType;
String[] mAutofillHints;
int mCheckSetId;
List<GuidedAction> mSubActions;
Intent mIntent;
protected GuidedAction() {
super(0);
}
private void setFlags(int flag, int mask) {
mActionFlags = (mActionFlags & ~mask) | (flag & mask);
}
/**
* Returns the title of this action.
* @return The title set when this action was built.
*/
public CharSequence getTitle() {
return getLabel1();
}
/**
* Sets the title of this action.
* @param title The title set when this action was built.
*/
public void setTitle(CharSequence title) {
setLabel1(title);
}
/**
* Returns the optional title text to edit. When not null, it is being edited instead of
* {@link #getTitle()}.
* @return Optional title text to edit instead of {@link #getTitle()}.
*/
public CharSequence getEditTitle() {
return mEditTitle;
}
/**
* Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}.
* @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}.
*/
public void setEditTitle(CharSequence editTitle) {
mEditTitle = editTitle;
}
/**
* Returns the optional description text to edit. When not null, it is being edited instead of
* {@link #getDescription()}.
* @return Optional description text to edit instead of {@link #getDescription()}.
*/
public CharSequence getEditDescription() {
return mEditDescription;
}
/**
* Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}.
* @param editDescription Optional description text to edit instead of
* {@link #setDescription(CharSequence)}.
*/
public void setEditDescription(CharSequence editDescription) {
mEditDescription = editDescription;
}
/**
* Returns true if {@link #getEditTitle()} is not null. When true, the {@link #getEditTitle()}
* is being edited instead of {@link #getTitle()}.
* @return true if {@link #getEditTitle()} is not null.
*/
public boolean isEditTitleUsed() {
return mEditTitle != null;
}
/**
* Returns the description of this action.
* @return The description of this action.
*/
public CharSequence getDescription() {
return getLabel2();
}
/**
* Sets the description of this action.
* @param description The description of the action.
*/
public void setDescription(CharSequence description) {
setLabel2(description);
}
/**
* Returns the intent associated with this action.
* @return The intent set when this action was built.
*/
public Intent getIntent() {
return mIntent;
}
/**
* Sets the intent of this action.
* @param intent New intent to set on this action.
*/
public void setIntent(Intent intent) {
mIntent = intent;
}
/**
* Returns whether this action title is editable.
* @return true if the action title is editable, false otherwise.
*/
public boolean isEditable() {
return mEditable == EDITING_TITLE;
}
/**
* Returns whether this action description is editable.
* @return true if the action description is editable, false otherwise.
*/
public boolean isDescriptionEditable() {
return mEditable == EDITING_DESCRIPTION;
}
/**
* Returns if this action has editable title or editable description.
* @return True if this action has editable title or editable description, false otherwise.
*/
public boolean hasTextEditable() {
return mEditable == EDITING_TITLE || mEditable == EDITING_DESCRIPTION;
}
/**
* Returns whether this action can be activated to edit, e.g. a DatePicker.
* @return true if the action can be activated to edit.
*/
public boolean hasEditableActivatorView() {
return mEditable == EDITING_ACTIVATOR_VIEW;
}
/**
* Returns InputType of action title in editing; only valid when {@link #isEditable()} is true.
* @return InputType of action title in editing.
*/
public int getEditInputType() {
return mEditInputType;
}
/**
* Returns InputType of action description in editing; only valid when
* {@link #isDescriptionEditable()} is true.
* @return InputType of action description in editing.
*/
public int getDescriptionEditInputType() {
return mDescriptionEditInputType;
}
/**
* Returns InputType of action title not in editing.
* @return InputType of action title not in editing.
*/
public int getInputType() {
return mInputType;
}
/**
* Returns InputType of action description not in editing.
* @return InputType of action description not in editing.
*/
public int getDescriptionInputType() {
return mDescriptionInputType;
}
/**
* Returns whether this action is checked.
* @return true if the action is currently checked, false otherwise.
*/
public boolean isChecked() {
return (mActionFlags & PF_CHECKED) == PF_CHECKED;
}
/**
* Sets whether this action is checked.
* @param checked Whether this action should be checked.
*/
public void setChecked(boolean checked) {
setFlags(checked ? PF_CHECKED : 0, PF_CHECKED);
}
/**
* Returns the check set id this action is a part of. All actions in the same list with the same
* check set id are considered linked. When one of the actions within that set is selected, that
* action becomes checked, while all the other actions become unchecked.
*
* @return an integer representing the check set this action is a part of, or
* {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
* this action is not a checkbox or radiobutton.
*/
public int getCheckSetId() {
return mCheckSetId;
}
/**
* Returns whether this action is has a multiline description.
* @return true if the action was constructed as having a multiline description, false
* otherwise.
*/
public boolean hasMultilineDescription() {
return (mActionFlags & PF_MULTI_LINE_DESCRIPTION) == PF_MULTI_LINE_DESCRIPTION;
}
/**
* Returns whether this action is enabled.
* @return true if the action is currently enabled, false otherwise.
*/
public boolean isEnabled() {
return (mActionFlags & PF_ENABLED) == PF_ENABLED;
}
/**
* Sets whether this action is enabled.
* @param enabled Whether this action should be enabled.
*/
public void setEnabled(boolean enabled) {
setFlags(enabled ? PF_ENABLED : 0, PF_ENABLED);
}
/**
* Returns whether this action is focusable.
* @return true if the action is currently focusable, false otherwise.
*/
public boolean isFocusable() {
return (mActionFlags & PF_FOCUSABLE) == PF_FOCUSABLE;
}
/**
* Sets whether this action is focusable.
* @param focusable Whether this action should be focusable.
*/
public void setFocusable(boolean focusable) {
setFlags(focusable ? PF_FOCUSABLE : 0, PF_FOCUSABLE);
}
/**
* Returns autofill hints, see {@link android.view.View#setAutofillHints(String...)}.
*/
public String[] getAutofillHints() {
return mAutofillHints;
}
/**
* Returns whether this action will request further user input when selected, such as showing
* another GuidedStepFragment or launching a new activity. Configured during construction.
* @return true if the action will request further user input when selected, false otherwise.
*/
public boolean hasNext() {
return (mActionFlags & PF_HAS_NEXT) == PF_HAS_NEXT;
}
/**
* Returns whether the action will only display information and is thus not clickable. If both
* this and {@link #hasNext()} are true, infoOnly takes precedence. The default is false. For
* example, this might represent e.g. the amount of storage a document uses, or the cost of an
* app.
* @return true if will only display information, false otherwise.
*/
public boolean infoOnly() {
return (mActionFlags & PF_INFO_ONLY) == PF_INFO_ONLY;
}
/**
* Change sub actions list.
* @param actions Sub actions list to set on this action. Sets null to disable sub actions.
*/
public void setSubActions(List<GuidedAction> actions) {
mSubActions = actions;
}
/**
* @return List of sub actions or null if sub actions list is not enabled.
*/
public List<GuidedAction> getSubActions() {
return mSubActions;
}
/**
* @return True if has sub actions list, even it's currently empty.
*/
public boolean hasSubActions() {
return mSubActions != null;
}
/**
* Returns true if Action will be saved to instanceState and restored later, false otherwise.
* The default value is true. When isAutoSaveRestoreEnabled() is true and {@link #getId()} is
* not {@link #NO_ID}:
* <li>{@link #isEditable()} is true: save text of {@link #getTitle()}</li>
* <li>{@link #isDescriptionEditable()} is true: save text of {@link #getDescription()}</li>
* <li>{@link #getCheckSetId()} is not {@link #NO_CHECK_SET}: save {@link #isChecked()}}</li>
* <li>{@link GuidedDatePickerAction} will be saved</li>
* App may explicitly disable auto restore and handle by itself. App should override Fragment
* onSaveInstanceState() and onCreateActions()
* @return True if Action will be saved to instanceState and restored later, false otherwise.
*/
public final boolean isAutoSaveRestoreEnabled() {
return (mActionFlags & PF_AUTORESTORE) == PF_AUTORESTORE;
}
/**
* Save action into a bundle using a given key. When isAutoRestoreEna() is true:
* <li>{@link #isEditable()} is true: save text of {@link #getTitle()}</li>
* <li>{@link #isDescriptionEditable()} is true: save text of {@link #getDescription()}</li>
* <li>{@link #getCheckSetId()} is not {@link #NO_CHECK_SET}: save {@link #isChecked()}}</li>
* <li>{@link GuidedDatePickerAction} will be saved</li>
* Subclass may override this method.
* @param bundle Bundle to save the Action.
* @param key Key used to save the Action.
*/
public void onSaveInstanceState(Bundle bundle, String key) {
if (needAutoSaveTitle() && getTitle() != null) {
bundle.putString(key, getTitle().toString());
} else if (needAutoSaveDescription() && getDescription() != null) {
bundle.putString(key, getDescription().toString());
} else if (getCheckSetId() != NO_CHECK_SET) {
bundle.putBoolean(key, isChecked());
}
}
/**
* Restore action from a bundle using a given key. When isAutoRestore() is true:
* <li>{@link #isEditable()} is true: save text of {@link #getTitle()}</li>
* <li>{@link #isDescriptionEditable()} is true: save text of {@link #getDescription()}</li>
* <li>{@link #getCheckSetId()} is not {@link #NO_CHECK_SET}: save {@link #isChecked()}}</li>
* <li>{@link GuidedDatePickerAction} will be saved</li>
* Subclass may override this method.
* @param bundle Bundle to restore the Action from.
* @param key Key used to restore the Action.
*/
public void onRestoreInstanceState(Bundle bundle, String key) {
if (needAutoSaveTitle()) {
String title = bundle.getString(key);
if (title != null) {
setTitle(title);
}
} else if (needAutoSaveDescription()) {
String description = bundle.getString(key);
if (description != null) {
setDescription(description);
}
} else if (getCheckSetId() != NO_CHECK_SET) {
setChecked(bundle.getBoolean(key, isChecked()));
}
}
static boolean isPasswordVariant(int inputType) {
final int variation = inputType & InputType.TYPE_MASK_VARIATION;
return variation == InputType.TYPE_TEXT_VARIATION_PASSWORD
|| variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|| variation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD;
}
final boolean needAutoSaveTitle() {
return isEditable() && !isPasswordVariant(getEditInputType());
}
final boolean needAutoSaveDescription() {
return isDescriptionEditable() && !isPasswordVariant(getDescriptionEditInputType());
}
}