travisc ab2fec6da4 Move lib/src/ to lib/java/, and lib/jvmtests/javatests/ to lib/javatests/.
Bazel is happier if Java/Java test roots are named 'java' and 'javatests', and
this will mean that once we create a BUILD file for
android/support/design/{widget,internal}/ we'll no longer need a custom package
specified in our build (which tends to cause build problems that manifest quite
weirdly). This commit doesn't attempt to refactor the build at all yet, and is
just a pure move.

PiperOrigin-RevId: 178060739
2018-01-11 10:50:18 -05:00

694 lines
25 KiB
Java

/*
* Copyright (C) 2016 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 android.support.design.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.BoolRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.support.annotation.IntDef;
import android.support.annotation.IntegerRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.R;
import android.support.design.internal.BottomNavigationMenu;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.internal.BottomNavigationPresenter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.AbsSavedState;
import android.support.v4.view.ViewCompat;
import android.support.v7.content.res.AppCompatResources;
import android.support.v7.view.SupportMenuInflater;
import android.support.v7.view.menu.MenuBuilder;
import android.support.v7.widget.TintTypedArray;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Represents a standard bottom navigation bar for application. It is an implementation of <a
* href="https://material.google.com/components/bottom-navigation.html">material design bottom
* navigation</a>.
*
* <p>Bottom navigation bars make it easy for users to explore and switch between top-level views in
* a single tap. They should be used when an application has three to five top-level destinations.
*
* <p>The bar can disappear on scroll, based on {@link HideBottomViewOnScrollBehavior}, when it is
* placed within a {@link CoordinatorLayout} and one of the children within the {@link
* CoordinatorLayout} is scrolled. This behavior is only set if the {@code layout_behavior} property
* is set to {@link HideBottomViewOnScrollBehavior}.
*
* <p>The bar contents can be populated by specifying a menu resource file. Each menu item title,
* icon and enabled state will be used for displaying bottom navigation bar items. Menu items can
* also be used for programmatically selecting which destination is currently active. It can be done
* using {@code MenuItem#setChecked(true)}
*
* <pre>
* layout resource file:
* &lt;android.support.design.widget.BottomNavigationView
* xmlns:android="http://schemas.android.com/apk/res/android"
* xmlns:app="http://schema.android.com/apk/res/res-auto"
* android:id="@+id/navigation"
* android:layout_width="match_parent"
* android:layout_height="56dp"
* android:layout_gravity="start"
* app:menu="@menu/my_navigation_items" /&gt;
*
* res/menu/my_navigation_items.xml:
* &lt;menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
* &lt;item android:id="@+id/action_search"
* android:title="@string/menu_search"
* android:icon="@drawable/ic_search" /&gt;
* &lt;item android:id="@+id/action_settings"
* android:title="@string/menu_settings"
* android:icon="@drawable/ic_add" /&gt;
* &lt;item android:id="@+id/action_navigation"
* android:title="@string/menu_navigation"
* android:icon="@drawable/ic_action_navigation_menu" /&gt;
* &lt;/menu&gt;
* </pre>
*/
public class BottomNavigationView extends FrameLayout {
private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
private static final int[] DISABLED_STATE_SET = {-android.R.attr.state_enabled};
private static final int MENU_PRESENTER_ID = 1;
/**
* Shifting mode enabled only when BottomNavigationView has 3 or more children (default).
*
* @see #setShiftingMode(int)
* @see #getShiftingMode()
* @deprecated use {@link LabelVisibilityMode instead}
*/
@Deprecated public static final int SHIFTING_MODE_AUTO = -1;
/**
* Shifting mode disabled in all cases.
*
* @see #setShiftingMode(int)
* @see #getShiftingMode()
* @deprecated use {@link LabelVisibilityMode instead}
*/
@Deprecated public static final int SHIFTING_MODE_OFF = 0;
/**
* Shifting mode enabled in all cases.
*
* @see #setShiftingMode(int)
* @see #getShiftingMode()
* @deprecated use {@link LabelVisibilityMode instead}
*/
@Deprecated public static final int SHIFTING_MODE_ON = 1;
/**
* Shifting mode flag enum for this {@link BottomNavigationView}. Shifting mode hides text labels
* for child views when enabled, unless the child view is selected. Shifting mode is enabled for
* {@link BottomNavigationView}s with more than 3 children by default, or for {@link
* BottomNavigationView}s with any number of children if shifting mode flag is set to {@link
* ShiftingMode#SHIFTING_MODE_ON}.
*
* @see <a
* href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-specs">Material
* Design guidelines</a>
* @deprecated use {@link LabelVisibilityMode instead}
*/
@Deprecated
@IntDef({SHIFTING_MODE_AUTO, SHIFTING_MODE_OFF, SHIFTING_MODE_ON})
@Retention(RetentionPolicy.SOURCE)
public @interface ShiftingMode {}
private final MenuBuilder mMenu;
private final BottomNavigationMenuView mMenuView;
private final BottomNavigationPresenter mPresenter = new BottomNavigationPresenter();
private MenuInflater mMenuInflater;
private OnNavigationItemSelectedListener mSelectedListener;
private OnNavigationItemReselectedListener mReselectedListener;
/**
* Label is shown when {@link ShiftingMode} is enabled, or hidden when it is not.
*
* @see #setLabelVisibilityMode(int)
* @see #getLabelVisibilityMode()
* @deprecated use one of the other {@link LabelVisibilityMode}s instead
*/
@Deprecated public static final int LABEL_VISIBILITY_LEGACY = -1;
/**
* Label is shown on the selected navigation item.
*
* @see #setLabelVisibilityMode(int)
* @see #getLabelVisibilityMode()
*/
public static final int LABEL_VISIBILITY_SELECTED = 0;
/**
* Label is shown on all navigation items.
*
* @see #setLabelVisibilityMode(int)
* @see #getLabelVisibilityMode()
*/
public static final int LABEL_VISIBILITY_LABELED = 1;
/**
* Label is not shown on any navigation items.
*
* @see #setLabelVisibilityMode(int)
* @see #getLabelVisibilityMode()
*/
public static final int LABEL_VISIBILITY_UNLABELED = 2;
/**
* Label visibility mode enum for this {@link BottomNavigationView}.
*
* <p>The label visibility mode determines whether to show or hide labels in the navigation items.
* Setting the label visibility mode to {@link LabelVisibilityMode#LABEL_VISIBILITY_SELECTED} sets
* the label to only show when selected, setting it to {@link
* LabelVisibilityMode#LABEL_VISIBILITY_LABELED} sets the label to always show, and {@link
* LabelVisibilityMode#LABEL_VISIBILITY_UNLABELED} sets the label to never show.
*
* <p>Setting the label visibility mode to {@link LabelVisibilityMode#LABEL_VISIBILITY_LEGACY}
* sets the label to behave as it used to with {@link ShiftingMode}.
*/
@IntDef({
LABEL_VISIBILITY_LEGACY,
LABEL_VISIBILITY_SELECTED,
LABEL_VISIBILITY_LABELED,
LABEL_VISIBILITY_UNLABELED
})
@Retention(RetentionPolicy.SOURCE)
public @interface LabelVisibilityMode {}
public BottomNavigationView(Context context) {
this(context, null);
}
public BottomNavigationView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
ThemeUtils.checkAppCompatTheme(context);
// Create the menu
mMenu = new BottomNavigationMenu(context);
mMenuView = new BottomNavigationMenuView(context);
FrameLayout.LayoutParams params =
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
mMenuView.setLayoutParams(params);
mPresenter.setBottomNavigationMenuView(mMenuView);
mPresenter.setId(MENU_PRESENTER_ID);
mMenuView.setPresenter(mPresenter);
mMenu.addMenuPresenter(mPresenter);
mPresenter.initForMenu(getContext(), mMenu);
// Custom attributes
TintTypedArray a =
TintTypedArray.obtainStyledAttributes(
context,
attrs,
R.styleable.BottomNavigationView,
defStyleAttr,
R.style.Widget_Design_BottomNavigationView);
if (a.hasValue(R.styleable.BottomNavigationView_itemIconTint)) {
mMenuView.setIconTintList(a.getColorStateList(R.styleable.BottomNavigationView_itemIconTint));
} else {
mMenuView.setIconTintList(createDefaultColorStateList(android.R.attr.textColorSecondary));
}
if (a.hasValue(R.styleable.BottomNavigationView_itemTextColor)) {
mMenuView.setItemTextColor(
a.getColorStateList(R.styleable.BottomNavigationView_itemTextColor));
} else {
mMenuView.setItemTextColor(createDefaultColorStateList(android.R.attr.textColorSecondary));
}
if (a.hasValue(R.styleable.BottomNavigationView_elevation)) {
ViewCompat.setElevation(
this, a.getDimensionPixelSize(R.styleable.BottomNavigationView_elevation, 0));
}
if (a.hasValue(R.styleable.BottomNavigationView_shiftingMode)) {
@ShiftingMode
int shiftingMode =
a.getInt(R.styleable.BottomNavigationView_shiftingMode, SHIFTING_MODE_AUTO);
mMenuView.setShiftingMode(shiftingMode);
}
setLabelVisibilityMode(
a.getInteger(
R.styleable.BottomNavigationView_labelVisibilityMode, LABEL_VISIBILITY_LEGACY));
setItemHorizontalTranslation(
a.getBoolean(R.styleable.BottomNavigationView_itemHorizontalTranslation, true));
int itemBackground = a.getResourceId(R.styleable.BottomNavigationView_itemBackground, 0);
mMenuView.setItemBackgroundRes(itemBackground);
if (a.hasValue(R.styleable.BottomNavigationView_menu)) {
inflateMenu(a.getResourceId(R.styleable.BottomNavigationView_menu, 0));
}
a.recycle();
addView(mMenuView, params);
if (Build.VERSION.SDK_INT < 21) {
addCompatibilityTopDivider(context);
}
mMenu.setCallback(
new MenuBuilder.Callback() {
@Override
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
if (mReselectedListener != null && item.getItemId() == getSelectedItemId()) {
mReselectedListener.onNavigationItemReselected(item);
return true; // item is already selected
}
return mSelectedListener != null && !mSelectedListener.onNavigationItemSelected(item);
}
@Override
public void onMenuModeChange(MenuBuilder menu) {}
});
}
/**
* Set a listener that will be notified when a bottom navigation item is selected. This listener
* will also be notified when the currently selected item is reselected, unless an {@link
* OnNavigationItemReselectedListener} has also been set.
*
* @param listener The listener to notify
* @see #setOnNavigationItemReselectedListener(OnNavigationItemReselectedListener)
*/
public void setOnNavigationItemSelectedListener(
@Nullable OnNavigationItemSelectedListener listener) {
mSelectedListener = listener;
}
/**
* Set a listener that will be notified when the currently selected bottom navigation item is
* reselected. This does not require an {@link OnNavigationItemSelectedListener} to be set.
*
* @param listener The listener to notify
* @see #setOnNavigationItemSelectedListener(OnNavigationItemSelectedListener)
*/
public void setOnNavigationItemReselectedListener(
@Nullable OnNavigationItemReselectedListener listener) {
mReselectedListener = listener;
}
/** Returns the {@link Menu} instance associated with this bottom navigation bar. */
@NonNull
public Menu getMenu() {
return mMenu;
}
/**
* Inflate a menu resource into this navigation view.
*
* <p>Existing items in the menu will not be modified or removed.
*
* @param resId ID of a menu resource to inflate
*/
public void inflateMenu(int resId) {
mPresenter.setUpdateSuspended(true);
getMenuInflater().inflate(resId, mMenu);
mPresenter.setUpdateSuspended(false);
mPresenter.updateMenuView(true);
}
/** @return The maximum number of items that can be shown in BottomNavigationView. */
public int getMaxItemCount() {
return BottomNavigationMenu.MAX_ITEM_COUNT;
}
/**
* Returns the tint which is applied to our menu items' icons.
*
* @see #setItemIconTintList(ColorStateList)
* @attr ref R.styleable#BottomNavigationView_itemIconTint
*/
@Nullable
public ColorStateList getItemIconTintList() {
return mMenuView.getIconTintList();
}
/**
* Set the tint which is applied to our menu items' icons.
*
* @param tint the tint to apply.
* @attr ref R.styleable#BottomNavigationView_itemIconTint
*/
public void setItemIconTintList(@Nullable ColorStateList tint) {
mMenuView.setIconTintList(tint);
}
/**
* Returns colors used for the different states (normal, selected, focused, etc.) of the menu item
* text.
*
* @see #setItemTextColor(ColorStateList)
* @return the ColorStateList of colors used for the different states of the menu items text.
* @attr ref R.styleable#BottomNavigationView_itemTextColor
*/
@Nullable
public ColorStateList getItemTextColor() {
return mMenuView.getItemTextColor();
}
/**
* Set the colors to use for the different states (normal, selected, focused, etc.) of the menu
* item text.
*
* @see #getItemTextColor()
* @attr ref R.styleable#BottomNavigationView_itemTextColor
*/
public void setItemTextColor(@Nullable ColorStateList textColor) {
mMenuView.setItemTextColor(textColor);
}
/**
* Returns the background resource of the menu items.
*
* @see #setItemBackgroundResource(int)
* @attr ref R.styleable#BottomNavigationView_itemBackground
*/
@DrawableRes
public int getItemBackgroundResource() {
return mMenuView.getItemBackgroundRes();
}
/**
* Set the background of our menu items to the given resource.
*
* @param resId The identifier of the resource.
* @attr ref R.styleable#BottomNavigationView_itemBackground
*/
public void setItemBackgroundResource(@DrawableRes int resId) {
mMenuView.setItemBackgroundRes(resId);
}
/**
* Returns the currently selected menu item ID, or zero if there is no menu.
*
* @see #setSelectedItemId(int)
*/
@IdRes
public int getSelectedItemId() {
return mMenuView.getSelectedItemId();
}
/**
* Set the selected menu item ID. This behaves the same as tapping on an item.
*
* @param itemId The menu item ID. If no item has this ID, the current selection is unchanged.
* @see #getSelectedItemId()
*/
public void setSelectedItemId(@IdRes int itemId) {
MenuItem item = mMenu.findItem(itemId);
if (item != null) {
if (!mMenu.performItemAction(item, mPresenter, 0)) {
item.setChecked(true);
}
}
}
/**
* Returns the current shifting mode flag used by this {@link BottomNavigationView}.
*
* @attr ref android.support.design.R.styleable#BottomNavigationView_shiftingMode
* @see #setShiftingMode(int)
* @deprecated use {@link BottomNavigationView#setLabelVisibilityMode} instead
*/
@Deprecated
@ShiftingMode
public int getShiftingMode() {
return mMenuView.getShiftingMode();
}
/**
* Set shifting mode flag for this {@link BottomNavigationView}. Enabling shifting mode hides the
* text labels of menu items in this {@link BottomNavigationView} unless the menu item is
* selected. If this flag is set to {@link ShiftingMode#SHIFTING_MODE_OFF}, this menu will not
* have shifting behavior even if it has more than 3 children. If this flag is set to {@link
* ShiftingMode#SHIFTING_MODE_ON}, this menu will have shifting behavior for any number of
* children. If this flag is set to {@link ShiftingMode#SHIFTING_MODE_AUTO} this menu will have
* shifting behavior only if it has 3 or more children.
*
* @param shiftingMode one of {@link ShiftingMode#SHIFTING_MODE_OFF}, {@link
* ShiftingMode#SHIFTING_MODE_ON}, or {@link ShiftingMode#SHIFTING_MODE_AUTO}
* @attr ref android.support.design.R.styleable#BottomNavigationView_shiftingMode
* @see <a
* href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-specs">Material
* Design guidelines</a>
* @see #getShiftingMode()
* @deprecated use {@link BottomNavigationView#setLabelVisibilityMode} instead
*/
@Deprecated
public void setShiftingMode(@ShiftingMode int shiftingMode) {
if (mMenuView.getShiftingMode() != shiftingMode) {
mMenuView.setShiftingMode(shiftingMode);
mPresenter.updateMenuView(false /* cleared */);
}
}
/**
* Sets the navigation items' label visibility mode.
*
* <p>The label is either always shown, never shown, or only shown when activated. Also supports
* legacy mode, which uses {@link ShiftingMode} to decide whether the label should be shown.
*
* @attr ref android.support.design.R.styleable#BottomNavigationView_labelVisibilityMode
* @param labelVisibilityMode mode which decides whether or not the label should be shown. Can be
* one of {@link LabelVisibilityMode#LABEL_VISIBILITY_LEGACY}, {@link
* LabelVisibilityMode#LABEL_VISIBILITY_SELECTED}, {@link
* LabelVisibilityMode#LABEL_VISIBILITY_LABELED}, or {@link
* LabelVisibilityMode#LABEL_VISIBILITY_UNLABELED}
* @see #getLabelVisibilityMode()
*/
public void setLabelVisibilityMode(@LabelVisibilityMode int labelVisibilityMode) {
if (mMenuView.getLabelVisibilityMode() != labelVisibilityMode) {
mMenuView.setLabelVisibilityMode(labelVisibilityMode);
mPresenter.updateMenuView(false);
}
}
/**
* Sets the navigation items' label visibility mode using a resource ID.
*
* <p>The label is either always shown, never shown, or only shown when activated. Also supports
* legacy mode, which uses {@link ShiftingMode} to decide whether the label should be shown.
*
* @attr ref android.support.design.R.styleable#BottomNavigationView_labelVisibilityMode
* @param labelVisibilityModeId resource ID for the mode which decides whether or not the label
* should be shown. Can be one of {@link LabelVisibilityMode#LABEL_VISIBILITY_LEGACY}, {@link
* LabelVisibilityMode#LABEL_VISIBILITY_SELECTED}, {@link
* LabelVisibilityMode#LABEL_VISIBILITY_LABELED}, or {@link
* LabelVisibilityMode#LABEL_VISIBILITY_UNLABELED}
* @see #getLabelVisibilityMode()
*/
public void setLabelVisibilityModeResource(@IntegerRes int labelVisibilityModeId) {
setLabelVisibilityMode(getContext().getResources().getInteger(labelVisibilityModeId));
}
/**
* Returns the current label visibility mode used by this {@link BottomNavigationView}.
*
* @attr ref android.support.design.R.styleable#BottomNavigationView_labelVisibilityMode
* @see #setLabelVisibilityMode(int)
*/
@LabelVisibilityMode
public int getLabelVisibilityMode() {
return mMenuView.getLabelVisibilityMode();
}
/**
* Sets whether the menu items horizontally translate when in shifting mode.
*
* @param itemHorizontalTranslation whether the items horizontally translate in shifting mode
* @see #getItemHorizontalTranslation()
*/
public void setItemHorizontalTranslation(boolean itemHorizontalTranslation) {
if (mMenuView.getItemHorizontalTranslation() != itemHorizontalTranslation) {
mMenuView.setItemHorizontalTranslation(itemHorizontalTranslation);
mPresenter.updateMenuView(false);
}
}
/**
* Sets whether the menu items horizontally translate when in shifting mode using a resource ID.
*
* @param itemHorizontalTranslation whether the items horizontally translate in shifting mode
* @see #getItemHorizontalTranslation()
*/
public void setItemHorizontalTranslation(@BoolRes int itemHorizontalTranslation) {
setItemHorizontalTranslation(getContext().getResources().getBoolean(itemHorizontalTranslation));
}
/**
* Returns whether the menu items horizontally translate in shifting mode.
*
* @return whether the menu items horizontally translate in shifting mode
* @see #setItemHorizontalTranslation(boolean)
*/
public boolean getItemHorizontalTranslation() {
return mMenuView.getItemHorizontalTranslation();
}
/** Listener for handling selection events on bottom navigation items. */
public interface OnNavigationItemSelectedListener {
/**
* Called when an item in the bottom navigation menu is selected.
*
* @param item The selected item
* @return true to display the item as the selected item and false if the item should not be
* selected. Consider setting non-selectable items as disabled preemptively to make them
* appear non-interactive.
*/
boolean onNavigationItemSelected(@NonNull MenuItem item);
}
/** Listener for handling reselection events on bottom navigation items. */
public interface OnNavigationItemReselectedListener {
/**
* Called when the currently selected item in the bottom navigation menu is selected again.
*
* @param item The selected item
*/
void onNavigationItemReselected(@NonNull MenuItem item);
}
private void addCompatibilityTopDivider(Context context) {
View divider = new View(context);
divider.setBackgroundColor(
ContextCompat.getColor(context, R.color.design_bottom_navigation_shadow_color));
FrameLayout.LayoutParams dividerParams =
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
getResources().getDimensionPixelSize(R.dimen.design_bottom_navigation_shadow_height));
divider.setLayoutParams(dividerParams);
addView(divider);
}
private MenuInflater getMenuInflater() {
if (mMenuInflater == null) {
mMenuInflater = new SupportMenuInflater(getContext());
}
return mMenuInflater;
}
private ColorStateList createDefaultColorStateList(int baseColorThemeAttr) {
final TypedValue value = new TypedValue();
if (!getContext().getTheme().resolveAttribute(baseColorThemeAttr, value, true)) {
return null;
}
ColorStateList baseColor = AppCompatResources.getColorStateList(getContext(), value.resourceId);
if (!getContext()
.getTheme()
.resolveAttribute(android.support.v7.appcompat.R.attr.colorPrimary, value, true)) {
return null;
}
int colorPrimary = value.data;
int defaultColor = baseColor.getDefaultColor();
return new ColorStateList(
new int[][] {DISABLED_STATE_SET, CHECKED_STATE_SET, EMPTY_STATE_SET},
new int[] {
baseColor.getColorForState(DISABLED_STATE_SET, defaultColor), colorPrimary, defaultColor
});
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.menuPresenterState = new Bundle();
mMenu.savePresenterStates(savedState.menuPresenterState);
return savedState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
mMenu.restorePresenterStates(savedState.menuPresenterState);
}
static class SavedState extends AbsSavedState {
Bundle menuPresenterState;
public SavedState(Parcelable superState) {
super(superState);
}
public SavedState(Parcel source, ClassLoader loader) {
super(source, loader);
readFromParcel(source, loader);
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeBundle(menuPresenterState);
}
private void readFromParcel(Parcel in, ClassLoader loader) {
menuPresenterState = in.readBundle(loader);
}
public static final Creator<SavedState> CREATOR =
new ClassLoaderCreator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in, ClassLoader loader) {
return new SavedState(in, loader);
}
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in, null);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}