| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652 |
- package net.simonvt.menudrawer;
- import net.simonvt.menudrawer.compat.ActionBarHelper;
- import android.app.Activity;
- import android.content.Context;
- import android.content.res.TypedArray;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Rect;
- import android.graphics.drawable.Drawable;
- import android.graphics.drawable.GradientDrawable;
- import android.os.Build;
- import android.os.Bundle;
- import android.os.Parcel;
- import android.os.Parcelable;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.ViewParent;
- import android.view.ViewTreeObserver;
- import android.view.animation.AccelerateInterpolator;
- import android.view.animation.Interpolator;
- public abstract class MenuDrawer extends ViewGroup {
- /**
- * Callback interface for changing state of the drawer.
- */
- public interface OnDrawerStateChangeListener {
- /**
- * Called when the drawer state changes.
- *
- * @param oldState The old drawer state.
- * @param newState The new drawer state.
- */
- void onDrawerStateChange(int oldState, int newState);
- /**
- * Called when the drawer slides.
- *
- * @param openRatio Ratio for how open the menu is.
- * @param offsetPixels Current offset of the menu in pixels.
- */
- void onDrawerSlide(float openRatio, int offsetPixels);
- }
- /**
- * Callback that is invoked when the drawer is in the process of deciding whether it should intercept the touch
- * event. This lets the listener decide if the pointer is on a view that would disallow dragging of the drawer.
- * This is only called when the touch mode is {@link #TOUCH_MODE_FULLSCREEN}.
- */
- public interface OnInterceptMoveEventListener {
- /**
- * Called for each child the pointer i on when the drawer is deciding whether to intercept the touch event.
- *
- * @param v View to test for draggability
- * @param delta Delta drag in pixels
- * @param x X coordinate of the active touch point
- * @param y Y coordinate of the active touch point
- * @return true if view is draggable by delta dx.
- */
- boolean isViewDraggable(View v, int delta, int x, int y);
- }
- public enum Type {
- /**
- * Positions the drawer behind the content.
- */
- BEHIND,
- /**
- * A static drawer that can not be dragged.
- */
- STATIC,
- /**
- * Positions the drawer on top of the content.
- */
- OVERLAY,
- }
- /**
- * Tag used when logging.
- */
- private static final String TAG = "MenuDrawer";
- /**
- * Indicates whether debug code should be enabled.
- */
- private static final boolean DEBUG = false;
- /**
- * The time between each frame when animating the drawer.
- */
- protected static final int ANIMATION_DELAY = 1000 / 60;
- /**
- * The default touch bezel size of the drawer in dp.
- */
- private static final int DEFAULT_DRAG_BEZEL_DP = 24;
- /**
- * The default drop shadow size in dp.
- */
- private static final int DEFAULT_DROP_SHADOW_DP = 6;
- /**
- * Drag mode for sliding only the content view.
- */
- public static final int MENU_DRAG_CONTENT = 0;
- /**
- * Drag mode for sliding the entire window.
- */
- public static final int MENU_DRAG_WINDOW = 1;
- /**
- * Disallow opening the drawer by dragging the screen.
- */
- public static final int TOUCH_MODE_NONE = 0;
- /**
- * Allow opening drawer only by dragging on the edge of the screen.
- */
- public static final int TOUCH_MODE_BEZEL = 1;
- /**
- * Allow opening drawer by dragging anywhere on the screen.
- */
- public static final int TOUCH_MODE_FULLSCREEN = 2;
- /**
- * Indicates that the drawer is currently closed.
- */
- public static final int STATE_CLOSED = 0;
- /**
- * Indicates that the drawer is currently closing.
- */
- public static final int STATE_CLOSING = 1;
- /**
- * Indicates that the drawer is currently being dragged by the user.
- */
- public static final int STATE_DRAGGING = 2;
- /**
- * Indicates that the drawer is currently opening.
- */
- public static final int STATE_OPENING = 4;
- /**
- * Indicates that the drawer is currently open.
- */
- public static final int STATE_OPEN = 8;
- /**
- * Indicates whether to use {@link View#setTranslationX(float)} when positioning views.
- */
- static final boolean USE_TRANSLATIONS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
- /**
- * Time to animate the indicator to the new active view.
- */
- static final int INDICATOR_ANIM_DURATION = 800;
- /**
- * The maximum animation duration.
- */
- private static final int DEFAULT_ANIMATION_DURATION = 600;
- /**
- * Interpolator used when animating the drawer open/closed.
- */
- protected static final Interpolator SMOOTH_INTERPOLATOR = new SmoothInterpolator();
- /**
- * Interpolator used for stretching/retracting the active indicator.
- */
- protected static final Interpolator INDICATOR_INTERPOLATOR = new AccelerateInterpolator();
- /**
- * Drawable used as menu overlay.
- */
- protected Drawable mMenuOverlay;
- /**
- * Defines whether the drop shadow is enabled.
- */
- protected boolean mDropShadowEnabled;
- /**
- * The color of the drop shadow.
- */
- protected int mDropShadowColor;
- /**
- * Drawable used as content drop shadow onto the menu.
- */
- protected Drawable mDropShadowDrawable;
- private boolean mCustomDropShadow;
- /**
- * The size of the content drop shadow.
- */
- protected int mDropShadowSize;
- /**
- * Bitmap used to indicate the active view.
- */
- protected Bitmap mActiveIndicator;
- /**
- * The currently active view.
- */
- protected View mActiveView;
- /**
- * Position of the active view. This is compared to View#getTag(R.id.mdActiveViewPosition) when drawing the
- * indicator.
- */
- protected int mActivePosition;
- /**
- * Whether the indicator should be animated between positions.
- */
- private boolean mAllowIndicatorAnimation;
- /**
- * Used when reading the position of the active view.
- */
- protected final Rect mActiveRect = new Rect();
- /**
- * Temporary {@link Rect} used for deciding whether the view should be invalidated so the indicator can be redrawn.
- */
- private final Rect mTempRect = new Rect();
- /**
- * The custom menu view set by the user.
- */
- private View mMenuView;
- /**
- * The parent of the menu view.
- */
- protected BuildLayerFrameLayout mMenuContainer;
- /**
- * The parent of the content view.
- */
- protected BuildLayerFrameLayout mContentContainer;
- /**
- * The size of the menu (width or height depending on the gravity).
- */
- protected int mMenuSize;
- /**
- * Indicates whether the menu is currently visible.
- */
- protected boolean mMenuVisible;
- /**
- * The drag mode of the drawer. Can be either {@link #MENU_DRAG_CONTENT} or {@link #MENU_DRAG_WINDOW}.
- */
- private int mDragMode = MENU_DRAG_CONTENT;
- /**
- * The current drawer state.
- *
- * @see #STATE_CLOSED
- * @see #STATE_CLOSING
- * @see #STATE_DRAGGING
- * @see #STATE_OPENING
- * @see #STATE_OPEN
- */
- protected int mDrawerState = STATE_CLOSED;
- /**
- * The touch bezel size of the drawer in px.
- */
- protected int mTouchBezelSize;
- /**
- * The touch area size of the drawer in px.
- */
- protected int mTouchSize;
- /**
- * Listener used to dispatch state change events.
- */
- private OnDrawerStateChangeListener mOnDrawerStateChangeListener;
- /**
- * Touch mode for the Drawer.
- * Possible values are {@link #TOUCH_MODE_NONE}, {@link #TOUCH_MODE_BEZEL} or {@link #TOUCH_MODE_FULLSCREEN}
- * Default: {@link #TOUCH_MODE_BEZEL}
- */
- protected int mTouchMode = TOUCH_MODE_BEZEL;
- /**
- * Indicates whether to use {@link View#LAYER_TYPE_HARDWARE} when animating the drawer.
- */
- protected boolean mHardwareLayersEnabled = true;
- /**
- * The Activity the drawer is attached to.
- */
- private Activity mActivity;
- /**
- * Scroller used when animating the indicator to a new position.
- */
- private FloatScroller mIndicatorScroller;
- /**
- * Runnable used when animating the indicator to a new position.
- */
- private Runnable mIndicatorRunnable = new Runnable() {
- @Override
- public void run() {
- animateIndicatorInvalidate();
- }
- };
- /**
- * The start position of the indicator when animating it to a new position.
- */
- protected int mIndicatorStartPos;
- /**
- * [0..1] value indicating the current progress of the animation.
- */
- protected float mIndicatorOffset;
- /**
- * Whether the indicator is currently animating.
- */
- protected boolean mIndicatorAnimating;
- /**
- * Bundle used to hold the drawers state.
- */
- protected Bundle mState;
- /**
- * The maximum duration of open/close animations.
- */
- protected int mMaxAnimationDuration = DEFAULT_ANIMATION_DURATION;
- /**
- * Callback that lets the listener override intercepting of touch events.
- */
- protected OnInterceptMoveEventListener mOnInterceptMoveEventListener;
- protected SlideDrawable mSlideDrawable;
- protected Drawable mThemeUpIndicator;
- protected boolean mDrawerIndicatorEnabled;
- private ActionBarHelper mActionBarHelper;
- private int mCurrentUpContentDesc;
- private int mDrawerOpenContentDesc;
- private int mDrawerClosedContentDesc;
- /**
- * The position of the drawer.
- */
- private Position mPosition;
- private Position mResolvedPosition;
- private final Rect mIndicatorClipRect = new Rect();
- protected boolean mIsStatic;
- protected final Rect mDropShadowRect = new Rect();
- /**
- * Current offset.
- */
- protected float mOffsetPixels;
- /**
- * Whether an overlay should be drawn as the drawer is opened and closed.
- */
- protected boolean mDrawOverlay;
- /**
- * Attaches the MenuDrawer to the Activity.
- *
- * @param activity The activity that the MenuDrawer will be attached to.
- * @return The created MenuDrawer instance.
- */
- public static MenuDrawer attach(Activity activity) {
- return attach(activity, Type.BEHIND);
- }
- /**
- * Attaches the MenuDrawer to the Activity.
- *
- * @param activity The activity the menu drawer will be attached to.
- * @param type The {@link Type} of the drawer.
- * @return The created MenuDrawer instance.
- */
- public static MenuDrawer attach(Activity activity, Type type) {
- return attach(activity, type, Position.START);
- }
- /**
- * Attaches the MenuDrawer to the Activity.
- *
- * @param activity The activity the menu drawer will be attached to.
- * @param position Where to position the menu.
- * @return The created MenuDrawer instance.
- */
- public static MenuDrawer attach(Activity activity, Position position) {
- return attach(activity, Type.BEHIND, position);
- }
- /**
- * Attaches the MenuDrawer to the Activity.
- *
- * @param activity The activity the menu drawer will be attached to.
- * @param type The {@link Type} of the drawer.
- * @param position Where to position the menu.
- * @return The created MenuDrawer instance.
- */
- public static MenuDrawer attach(Activity activity, Type type, Position position) {
- return attach(activity, type, position, MENU_DRAG_CONTENT);
- }
- /**
- * Attaches the MenuDrawer to the Activity.
- *
- * @param activity The activity the menu drawer will be attached to.
- * @param type The {@link Type} of the drawer.
- * @param position Where to position the menu.
- * @param dragMode The drag mode of the drawer. Can be either {@link MenuDrawer#MENU_DRAG_CONTENT}
- * or {@link MenuDrawer#MENU_DRAG_WINDOW}.
- * @return The created MenuDrawer instance.
- */
- public static MenuDrawer attach(Activity activity, Type type, Position position, int dragMode) {
- MenuDrawer menuDrawer = createMenuDrawer(activity, dragMode, position, type);
- menuDrawer.setId(R.id.md__drawer);
- switch (dragMode) {
- case MenuDrawer.MENU_DRAG_CONTENT:
- attachToContent(activity, menuDrawer);
- break;
- case MenuDrawer.MENU_DRAG_WINDOW:
- attachToDecor(activity, menuDrawer);
- break;
- default:
- throw new RuntimeException("Unknown menu mode: " + dragMode);
- }
- return menuDrawer;
- }
- /**
- * Constructs the appropriate MenuDrawer based on the position.
- */
- private static MenuDrawer createMenuDrawer(Activity activity, int dragMode, Position position, Type type) {
- MenuDrawer drawer;
- if (type == Type.STATIC) {
- drawer = new StaticDrawer(activity);
- } else if (type == Type.OVERLAY) {
- drawer = new OverlayDrawer(activity, dragMode);
- if (position == Position.LEFT || position == Position.START) {
- drawer.setupUpIndicator(activity);
- }
- } else {
- drawer = new SlidingDrawer(activity, dragMode);
- if (position == Position.LEFT || position == Position.START) {
- drawer.setupUpIndicator(activity);
- }
- }
- drawer.mDragMode = dragMode;
- drawer.setPosition(position);
- return drawer;
- }
- /**
- * Attaches the menu drawer to the content view.
- */
- private static void attachToContent(Activity activity, MenuDrawer menuDrawer) {
- /**
- * Do not call mActivity#setContentView.
- * E.g. if using with a ListActivity, Activity#setContentView is overridden and dispatched to
- * MenuDrawer#setContentView, which then again would call Activity#setContentView.
- */
- ViewGroup content = (ViewGroup) activity.findViewById(android.R.id.content);
- content.removeAllViews();
- content.addView(menuDrawer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- }
- /**
- * Attaches the menu drawer to the window.
- */
- private static void attachToDecor(Activity activity, MenuDrawer menuDrawer) {
- ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
- ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0);
- decorView.removeAllViews();
- decorView.addView(menuDrawer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- menuDrawer.mContentContainer.addView(decorChild, decorChild.getLayoutParams());
- }
- MenuDrawer(Activity activity, int dragMode) {
- this(activity);
- mActivity = activity;
- mDragMode = dragMode;
- }
- public MenuDrawer(Context context) {
- this(context, null);
- }
- public MenuDrawer(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.menuDrawerStyle);
- }
- public MenuDrawer(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initDrawer(context, attrs, defStyle);
- }
- protected void initDrawer(Context context, AttributeSet attrs, int defStyle) {
- setWillNotDraw(false);
- setFocusable(false);
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MenuDrawer, R.attr.menuDrawerStyle,
- R.style.Widget_MenuDrawer);
- final Drawable contentBackground = a.getDrawable(R.styleable.MenuDrawer_mdContentBackground);
- final Drawable menuBackground = a.getDrawable(R.styleable.MenuDrawer_mdMenuBackground);
- mMenuSize = a.getDimensionPixelSize(R.styleable.MenuDrawer_mdMenuSize, dpToPx(240));
- final int indicatorResId = a.getResourceId(R.styleable.MenuDrawer_mdActiveIndicator, 0);
- if (indicatorResId != 0) {
- mActiveIndicator = BitmapFactory.decodeResource(getResources(), indicatorResId);
- }
- mDropShadowEnabled = a.getBoolean(R.styleable.MenuDrawer_mdDropShadowEnabled, true);
- mDropShadowDrawable = a.getDrawable(R.styleable.MenuDrawer_mdDropShadow);
- if (mDropShadowDrawable == null) {
- mDropShadowColor = a.getColor(R.styleable.MenuDrawer_mdDropShadowColor, 0xFF000000);
- } else {
- mCustomDropShadow = true;
- }
- mDropShadowSize = a.getDimensionPixelSize(R.styleable.MenuDrawer_mdDropShadowSize,
- dpToPx(DEFAULT_DROP_SHADOW_DP));
- mTouchBezelSize = a.getDimensionPixelSize(R.styleable.MenuDrawer_mdTouchBezelSize,
- dpToPx(DEFAULT_DRAG_BEZEL_DP));
- mAllowIndicatorAnimation = a.getBoolean(R.styleable.MenuDrawer_mdAllowIndicatorAnimation, false);
- mMaxAnimationDuration = a.getInt(R.styleable.MenuDrawer_mdMaxAnimationDuration, DEFAULT_ANIMATION_DURATION);
- final int slideDrawableResId = a.getResourceId(R.styleable.MenuDrawer_mdSlideDrawable, -1);
- if (slideDrawableResId != -1) {
- setSlideDrawable(slideDrawableResId);
- }
- mDrawerOpenContentDesc = a.getResourceId(R.styleable.MenuDrawer_mdDrawerOpenUpContentDescription, 0);
- mDrawerClosedContentDesc = a.getResourceId(R.styleable.MenuDrawer_mdDrawerClosedUpContentDescription, 0);
- mDrawOverlay = a.getBoolean(R.styleable.MenuDrawer_mdDrawOverlay, true);
- final int position = a.getInt(R.styleable.MenuDrawer_mdPosition, 0);
- setPosition(Position.fromValue(position));
- a.recycle();
- mMenuContainer = new NoClickThroughFrameLayout(context);
- mMenuContainer.setId(R.id.md__menu);
- mMenuContainer.setBackgroundDrawable(menuBackground);
- mContentContainer = new NoClickThroughFrameLayout(context);
- mContentContainer.setId(R.id.md__content);
- mContentContainer.setBackgroundDrawable(contentBackground);
- mMenuOverlay = new ColorDrawable(0xFF000000);
- mIndicatorScroller = new FloatScroller(SMOOTH_INTERPOLATOR);
- }
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- View menu = findViewById(R.id.mdMenu);
- if (menu != null) {
- removeView(menu);
- setMenuView(menu);
- }
- View content = findViewById(R.id.mdContent);
- if (content != null) {
- removeView(content);
- setContentView(content);
- }
- if (getChildCount() > 2) {
- throw new IllegalStateException(
- "Menu and content view added in xml must have id's @id/mdMenu and @id/mdContent");
- }
- }
- protected int dpToPx(int dp) {
- return (int) (getResources().getDisplayMetrics().density * dp + 0.5f);
- }
- protected boolean isViewDescendant(View v) {
- ViewParent parent = v.getParent();
- while (parent != null) {
- if (parent == this) {
- return true;
- }
- parent = parent.getParent();
- }
- return false;
- }
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- getViewTreeObserver().addOnScrollChangedListener(mScrollListener);
- }
- @Override
- protected void onDetachedFromWindow() {
- getViewTreeObserver().removeOnScrollChangedListener(mScrollListener);
- super.onDetachedFromWindow();
- }
- private boolean shouldDrawIndicator() {
- return mActiveView != null && mActiveIndicator != null && isViewDescendant(mActiveView);
- }
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- final int offsetPixels = (int) mOffsetPixels;
- if (mDrawOverlay && offsetPixels != 0) {
- drawOverlay(canvas);
- }
- if (mDropShadowEnabled && (offsetPixels != 0 || mIsStatic)) {
- drawDropShadow(canvas);
- }
- if (shouldDrawIndicator() && (offsetPixels != 0 || mIsStatic)) {
- drawIndicator(canvas);
- }
- }
- protected abstract void drawOverlay(Canvas canvas);
- private void drawDropShadow(Canvas canvas) {
- // Can't pass the position to the constructor, so wait with loading the drawable until the drop shadow is
- // actually drawn.
- if (mDropShadowDrawable == null) {
- setDropShadowColor(mDropShadowColor);
- }
- updateDropShadowRect();
- mDropShadowDrawable.setBounds(mDropShadowRect);
- mDropShadowDrawable.draw(canvas);
- }
- protected void updateDropShadowRect() {
- // This updates the rect for the static and sliding drawer. The overlay drawer has its own implementation.
- switch (getPosition()) {
- case LEFT:
- mDropShadowRect.top = 0;
- mDropShadowRect.bottom = getHeight();
- mDropShadowRect.right = ViewHelper.getLeft(mContentContainer);
- mDropShadowRect.left = mDropShadowRect.right - mDropShadowSize;
- break;
- case TOP:
- mDropShadowRect.left = 0;
- mDropShadowRect.right = getWidth();
- mDropShadowRect.bottom = ViewHelper.getTop(mContentContainer);
- mDropShadowRect.top = mDropShadowRect.bottom - mDropShadowSize;
- break;
- case RIGHT:
- mDropShadowRect.top = 0;
- mDropShadowRect.bottom = getHeight();
- mDropShadowRect.left = ViewHelper.getRight(mContentContainer);
- mDropShadowRect.right = mDropShadowRect.left + mDropShadowSize;
- break;
- case BOTTOM:
- mDropShadowRect.left = 0;
- mDropShadowRect.right = getWidth();
- mDropShadowRect.top = ViewHelper.getBottom(mContentContainer);
- mDropShadowRect.bottom = mDropShadowRect.top + mDropShadowSize;
- break;
- }
- }
- private void drawIndicator(Canvas canvas) {
- Integer position = (Integer) mActiveView.getTag(R.id.mdActiveViewPosition);
- final int pos = position == null ? 0 : position;
- if (pos == mActivePosition) {
- updateIndicatorClipRect();
- canvas.save();
- canvas.clipRect(mIndicatorClipRect);
- int drawLeft = 0;
- int drawTop = 0;
- switch (getPosition()) {
- case LEFT:
- case TOP:
- drawLeft = mIndicatorClipRect.left;
- drawTop = mIndicatorClipRect.top;
- break;
- case RIGHT:
- drawLeft = mIndicatorClipRect.right - mActiveIndicator.getWidth();
- drawTop = mIndicatorClipRect.top;
- break;
- case BOTTOM:
- drawLeft = mIndicatorClipRect.left;
- drawTop = mIndicatorClipRect.bottom - mActiveIndicator.getHeight();
- }
- canvas.drawBitmap(mActiveIndicator, drawLeft, drawTop, null);
- canvas.restore();
- }
- }
- /**
- * Update the {@link Rect} where the indicator is drawn.
- */
- protected void updateIndicatorClipRect() {
- mActiveView.getDrawingRect(mActiveRect);
- offsetDescendantRectToMyCoords(mActiveView, mActiveRect);
- final float openRatio = mIsStatic ? 1.0f : Math.abs(mOffsetPixels) / mMenuSize;
- final float interpolatedRatio = 1.f - INDICATOR_INTERPOLATOR.getInterpolation((1.f - openRatio));
- final int indicatorWidth = mActiveIndicator.getWidth();
- final int indicatorHeight = mActiveIndicator.getHeight();
- final int interpolatedWidth = (int) (indicatorWidth * interpolatedRatio);
- final int interpolatedHeight = (int) (indicatorHeight * interpolatedRatio);
- final int startPos = mIndicatorStartPos;
- int left = 0;
- int top = 0;
- int right = 0;
- int bottom = 0;
- switch (getPosition()) {
- case LEFT:
- case RIGHT:
- final int finalTop = mActiveRect.top + ((mActiveRect.height() - indicatorHeight) / 2);
- if (mIndicatorAnimating) {
- top = (int) (startPos + ((finalTop - startPos) * mIndicatorOffset));
- } else {
- top = finalTop;
- }
- bottom = top + indicatorHeight;
- break;
- case TOP:
- case BOTTOM:
- final int finalLeft = mActiveRect.left + ((mActiveRect.width() - indicatorWidth) / 2);
- if (mIndicatorAnimating) {
- left = (int) (startPos + ((finalLeft - startPos) * mIndicatorOffset));
- } else {
- left = finalLeft;
- }
- right = left + indicatorWidth;
- break;
- }
- switch (getPosition()) {
- case LEFT: {
- right = ViewHelper.getLeft(mContentContainer);
- left = right - interpolatedWidth;
- break;
- }
- case TOP: {
- bottom = ViewHelper.getTop(mContentContainer);
- top = bottom - interpolatedHeight;
- break;
- }
- case RIGHT: {
- left = ViewHelper.getRight(mContentContainer);
- right = left + interpolatedWidth;
- break;
- }
- case BOTTOM: {
- top = ViewHelper.getBottom(mContentContainer);
- bottom = top + interpolatedHeight;
- break;
- }
- }
- mIndicatorClipRect.left = left;
- mIndicatorClipRect.top = top;
- mIndicatorClipRect.right = right;
- mIndicatorClipRect.bottom = bottom;
- }
- private void setPosition(Position position) {
- mPosition = position;
- mResolvedPosition = getPosition();
- }
- protected Position getPosition() {
- final int layoutDirection = ViewHelper.getLayoutDirection(this);
- switch (mPosition) {
- case START:
- if (layoutDirection == LAYOUT_DIRECTION_RTL) {
- return Position.RIGHT;
- } else {
- return Position.LEFT;
- }
- case END:
- if (layoutDirection == LAYOUT_DIRECTION_RTL) {
- return Position.LEFT;
- } else {
- return Position.RIGHT;
- }
- }
- return mPosition;
- }
- @Override
- public void onRtlPropertiesChanged(int layoutDirection) {
- super.onRtlPropertiesChanged(layoutDirection);
- if (!mCustomDropShadow) setDropShadowColor(mDropShadowColor);
- if (getPosition() != mResolvedPosition) {
- mResolvedPosition = getPosition();
- setOffsetPixels(mOffsetPixels * -1);
- }
- if (mSlideDrawable != null) mSlideDrawable.setIsRtl(layoutDirection == LAYOUT_DIRECTION_RTL);
- requestLayout();
- invalidate();
- }
- /**
- * Sets the number of pixels the content should be offset.
- *
- * @param offsetPixels The number of pixels to offset the content by.
- */
- protected void setOffsetPixels(float offsetPixels) {
- final int oldOffset = (int) mOffsetPixels;
- final int newOffset = (int) offsetPixels;
- mOffsetPixels = offsetPixels;
- if (mSlideDrawable != null) {
- final float offset = Math.abs(mOffsetPixels) / mMenuSize;
- mSlideDrawable.setOffset(offset);
- updateUpContentDescription();
- }
- if (newOffset != oldOffset) {
- onOffsetPixelsChanged(newOffset);
- mMenuVisible = newOffset != 0;
- // Notify any attached listeners of the current open ratio
- final float openRatio = ((float) Math.abs(newOffset)) / mMenuSize;
- dispatchOnDrawerSlide(openRatio, newOffset);
- }
- }
- /**
- * Called when the number of pixels the content should be offset by has changed.
- *
- * @param offsetPixels The number of pixels to offset the content by.
- */
- protected abstract void onOffsetPixelsChanged(int offsetPixels);
- /**
- * Toggles the menu open and close with animation.
- */
- public void toggleMenu() {
- toggleMenu(true);
- }
- /**
- * Toggles the menu open and close.
- *
- * @param animate Whether open/close should be animated.
- */
- public abstract void toggleMenu(boolean animate);
- /**
- * Animates the menu open.
- */
- public void openMenu() {
- openMenu(true);
- }
- /**
- * Opens the menu.
- *
- * @param animate Whether open/close should be animated.
- */
- public abstract void openMenu(boolean animate);
- /**
- * Animates the menu closed.
- */
- public void closeMenu() {
- closeMenu(true);
- }
- /**
- * Closes the menu.
- *
- * @param animate Whether open/close should be animated.
- */
- public abstract void closeMenu(boolean animate);
- /**
- * Indicates whether the menu is currently visible.
- *
- * @return True if the menu is open, false otherwise.
- */
- public abstract boolean isMenuVisible();
- /**
- * Set the size of the menu drawer when open.
- *
- * @param size The size of the menu.
- */
- public abstract void setMenuSize(int size);
- /**
- * Returns the size of the menu.
- *
- * @return The size of the menu.
- */
- public int getMenuSize() {
- return mMenuSize;
- }
- /**
- * Set the active view.
- * If the mdActiveIndicator attribute is set, this View will have the indicator drawn next to it.
- *
- * @param v The active view.
- */
- public void setActiveView(View v) {
- setActiveView(v, 0);
- }
- /**
- * Set the active view.
- * If the mdActiveIndicator attribute is set, this View will have the indicator drawn next to it.
- *
- * @param v The active view.
- * @param position Optional position, usually used with ListView. v.setTag(R.id.mdActiveViewPosition, position)
- * must be called first.
- */
- public void setActiveView(View v, int position) {
- final View oldView = mActiveView;
- mActiveView = v;
- mActivePosition = position;
- if (mAllowIndicatorAnimation && oldView != null) {
- startAnimatingIndicator();
- }
- invalidate();
- }
- /**
- * Sets whether the indicator should be animated between active views.
- *
- * @param animate Whether the indicator should be animated between active views.
- */
- public void setAllowIndicatorAnimation(boolean animate) {
- if (animate != mAllowIndicatorAnimation) {
- mAllowIndicatorAnimation = animate;
- completeAnimatingIndicator();
- }
- }
- /**
- * Indicates whether the indicator should be animated between active views.
- *
- * @return Whether the indicator should be animated between active views.
- */
- public boolean getAllowIndicatorAnimation() {
- return mAllowIndicatorAnimation;
- }
- /**
- * Scroll listener that checks whether the active view has moved before the drawer is invalidated.
- */
- private ViewTreeObserver.OnScrollChangedListener mScrollListener = new ViewTreeObserver.OnScrollChangedListener() {
- @Override
- public void onScrollChanged() {
- if (mActiveView != null && isViewDescendant(mActiveView)) {
- mActiveView.getDrawingRect(mTempRect);
- offsetDescendantRectToMyCoords(mActiveView, mTempRect);
- if (mTempRect.left != mActiveRect.left || mTempRect.top != mActiveRect.top
- || mTempRect.right != mActiveRect.right || mTempRect.bottom != mActiveRect.bottom) {
- invalidate();
- }
- }
- }
- };
- /**
- * Starts animating the indicator to a new position.
- */
- private void startAnimatingIndicator() {
- mIndicatorStartPos = getIndicatorStartPos();
- mIndicatorAnimating = true;
- mIndicatorScroller.startScroll(0.0f, 1.0f, INDICATOR_ANIM_DURATION);
- animateIndicatorInvalidate();
- }
- /**
- * Returns the start position of the indicator.
- *
- * @return The start position of the indicator.
- */
- private int getIndicatorStartPos() {
- switch (getPosition()) {
- case TOP:
- return mIndicatorClipRect.left;
- case RIGHT:
- return mIndicatorClipRect.top;
- case BOTTOM:
- return mIndicatorClipRect.left;
- default:
- return mIndicatorClipRect.top;
- }
- }
- /**
- * Compute the touch area based on the touch mode.
- */
- protected void updateTouchAreaSize() {
- if (mTouchMode == TOUCH_MODE_BEZEL) {
- mTouchSize = mTouchBezelSize;
- } else if (mTouchMode == TOUCH_MODE_FULLSCREEN) {
- mTouchSize = getMeasuredWidth();
- } else {
- mTouchSize = 0;
- }
- }
- /**
- * Callback when each frame in the indicator animation should be drawn.
- */
- private void animateIndicatorInvalidate() {
- if (mIndicatorScroller.computeScrollOffset()) {
- mIndicatorOffset = mIndicatorScroller.getCurr();
- invalidate();
- if (!mIndicatorScroller.isFinished()) {
- postOnAnimation(mIndicatorRunnable);
- return;
- }
- }
- completeAnimatingIndicator();
- }
- /**
- * Called when the indicator animation has completed.
- */
- private void completeAnimatingIndicator() {
- mIndicatorOffset = 1.0f;
- mIndicatorAnimating = false;
- invalidate();
- }
- /**
- * Enables or disables offsetting the menu when dragging the drawer.
- *
- * @param offsetMenu True to offset the menu, false otherwise.
- */
- public abstract void setOffsetMenuEnabled(boolean offsetMenu);
- /**
- * Indicates whether the menu is being offset when dragging the drawer.
- *
- * @return True if the menu is being offset, false otherwise.
- */
- public abstract boolean getOffsetMenuEnabled();
- /**
- * Get the current state of the drawer.
- *
- * @return The state of the drawer.
- */
- public int getDrawerState() {
- return mDrawerState;
- }
- /**
- * Register a callback to be invoked when the drawer state changes.
- *
- * @param listener The callback that will run.
- */
- public void setOnDrawerStateChangeListener(OnDrawerStateChangeListener listener) {
- mOnDrawerStateChangeListener = listener;
- }
- /**
- * Register a callback that will be invoked when the drawer is about to intercept touch events.
- *
- * @param listener The callback that will be invoked.
- */
- public void setOnInterceptMoveEventListener(OnInterceptMoveEventListener listener) {
- mOnInterceptMoveEventListener = listener;
- }
- /**
- * Defines whether the drop shadow is enabled.
- *
- * @param enabled Whether the drop shadow is enabled.
- */
- public void setDropShadowEnabled(boolean enabled) {
- mDropShadowEnabled = enabled;
- invalidate();
- }
- protected GradientDrawable.Orientation getDropShadowOrientation() {
- // Gets the orientation for the static and sliding drawer. The overlay drawer provides its own implementation.
- switch (getPosition()) {
- case TOP:
- return GradientDrawable.Orientation.BOTTOM_TOP;
- case RIGHT:
- return GradientDrawable.Orientation.LEFT_RIGHT;
- case BOTTOM:
- return GradientDrawable.Orientation.TOP_BOTTOM;
- default:
- return GradientDrawable.Orientation.RIGHT_LEFT;
- }
- }
- /**
- * Sets the color of the drop shadow.
- *
- * @param color The color of the drop shadow.
- */
- public void setDropShadowColor(int color) {
- GradientDrawable.Orientation orientation = getDropShadowOrientation();
- final int endColor = color & 0x00FFFFFF;
- mDropShadowDrawable = new GradientDrawable(orientation,
- new int[] {
- color,
- endColor,
- });
- invalidate();
- }
- /**
- * Sets the drawable of the drop shadow.
- *
- * @param drawable The drawable of the drop shadow.
- */
- public void setDropShadow(Drawable drawable) {
- mDropShadowDrawable = drawable;
- mCustomDropShadow = drawable != null;
- invalidate();
- }
- /**
- * Sets the drawable of the drop shadow.
- *
- * @param resId The resource identifier of the the drawable.
- */
- public void setDropShadow(int resId) {
- setDropShadow(getResources().getDrawable(resId));
- }
- /**
- * Returns the drawable of the drop shadow.
- */
- public Drawable getDropShadow() {
- return mDropShadowDrawable;
- }
- /**
- * Sets the size of the drop shadow.
- *
- * @param size The size of the drop shadow in px.
- */
- public void setDropShadowSize(int size) {
- mDropShadowSize = size;
- invalidate();
- }
- /**
- * Animates the drawer slightly open until the user opens the drawer.
- */
- public abstract void peekDrawer();
- /**
- * Animates the drawer slightly open. If delay is larger than 0, this happens until the user opens the drawer.
- *
- * @param delay The delay (in milliseconds) between each run of the animation. If 0, this animation is only run
- * once.
- */
- public abstract void peekDrawer(long delay);
- /**
- * Animates the drawer slightly open. If delay is larger than 0, this happens until the user opens the drawer.
- *
- * @param startDelay The delay (in milliseconds) until the animation is first run.
- * @param delay The delay (in milliseconds) between each run of the animation. If 0, this animation is only run
- * once.
- */
- public abstract void peekDrawer(long startDelay, long delay);
- /**
- * Enables or disables the user of {@link View#LAYER_TYPE_HARDWARE} when animations views.
- *
- * @param enabled Whether hardware layers are enabled.
- */
- public abstract void setHardwareLayerEnabled(boolean enabled);
- /**
- * Sets the maximum duration of open/close animations.
- *
- * @param duration The maximum duration in milliseconds.
- */
- public void setMaxAnimationDuration(int duration) {
- mMaxAnimationDuration = duration;
- }
- /**
- * Sets whether an overlay should be drawn when sliding the drawer.
- *
- * @param drawOverlay Whether an overlay should be drawn when sliding the drawer.
- */
- public void setDrawOverlay(boolean drawOverlay) {
- mDrawOverlay = drawOverlay;
- }
- /**
- * Gets whether an overlay is drawn when sliding the drawer.
- *
- * @return Whether an overlay is drawn when sliding the drawer.
- */
- public boolean getDrawOverlay() {
- return mDrawOverlay;
- }
- protected void updateUpContentDescription() {
- final int upContentDesc = isMenuVisible() ? mDrawerOpenContentDesc : mDrawerClosedContentDesc;
- if (mDrawerIndicatorEnabled && mActionBarHelper != null && upContentDesc != mCurrentUpContentDesc) {
- mCurrentUpContentDesc = upContentDesc;
- mActionBarHelper.setActionBarDescription(upContentDesc);
- }
- }
- /**
- * Sets the drawable used as the drawer indicator.
- *
- * @param drawable The drawable used as the drawer indicator.
- */
- public void setSlideDrawable(int drawableRes) {
- setSlideDrawable(getResources().getDrawable(drawableRes));
- }
- /**
- * Sets the drawable used as the drawer indicator.
- *
- * @param drawable The drawable used as the drawer indicator.
- */
- public void setSlideDrawable(Drawable drawable) {
- mSlideDrawable = new SlideDrawable(drawable);
- mSlideDrawable.setIsRtl(ViewHelper.getLayoutDirection(this) == LAYOUT_DIRECTION_RTL);
- if (mActionBarHelper != null) {
- mActionBarHelper.setDisplayShowHomeAsUpEnabled(true);
- if (mDrawerIndicatorEnabled) {
- mActionBarHelper.setActionBarUpIndicator(mSlideDrawable,
- isMenuVisible() ? mDrawerOpenContentDesc : mDrawerClosedContentDesc);
- }
- }
- }
- /**
- * Sets up the drawer indicator. It cna then be shown with {@link #setDrawerIndicatorEnabled(boolean)}.
- *
- * @param activity The activity the drawer is attached to.
- */
- public void setupUpIndicator(Activity activity) {
- if (mActionBarHelper == null) {
- mActionBarHelper = new ActionBarHelper(activity);
- mThemeUpIndicator = mActionBarHelper.getThemeUpIndicator();
- if (mDrawerIndicatorEnabled) {
- mActionBarHelper.setActionBarUpIndicator(mSlideDrawable,
- isMenuVisible() ? mDrawerOpenContentDesc : mDrawerClosedContentDesc);
- }
- }
- }
- /**
- * Sets whether the drawer indicator should be enabled. {@link #setupUpIndicator(Activity)} must be
- * called first.
- *
- * @param enabled Whether the drawer indicator should enabled.
- */
- public void setDrawerIndicatorEnabled(boolean enabled) {
- if (mActionBarHelper == null) {
- throw new IllegalStateException("setupUpIndicator(Activity) has not been called");
- }
- mDrawerIndicatorEnabled = enabled;
- if (enabled) {
- mActionBarHelper.setActionBarUpIndicator(mSlideDrawable,
- isMenuVisible() ? mDrawerOpenContentDesc : mDrawerClosedContentDesc);
- } else {
- mActionBarHelper.setActionBarUpIndicator(mThemeUpIndicator, 0);
- }
- }
- /**
- * Indicates whether the drawer indicator is currently enabled.
- *
- * @return Whether the drawer indicator is enabled.
- */
- public boolean isDrawerIndicatorEnabled() {
- return mDrawerIndicatorEnabled;
- }
- /**
- * Returns the ViewGroup used as a parent for the menu view.
- *
- * @return The menu view's parent.
- */
- public ViewGroup getMenuContainer() {
- return mMenuContainer;
- }
- /**
- * Returns the ViewGroup used as a parent for the content view.
- *
- * @return The content view's parent.
- */
- public ViewGroup getContentContainer() {
- if (mDragMode == MENU_DRAG_CONTENT) {
- return mContentContainer;
- } else {
- return (ViewGroup) findViewById(android.R.id.content);
- }
- }
- /**
- * Set the menu view from a layout resource.
- *
- * @param layoutResId Resource ID to be inflated.
- */
- public void setMenuView(int layoutResId) {
- mMenuContainer.removeAllViews();
- mMenuView = LayoutInflater.from(getContext()).inflate(layoutResId, mMenuContainer, false);
- mMenuContainer.addView(mMenuView);
- }
- /**
- * Set the menu view to an explicit view.
- *
- * @param view The menu view.
- */
- public void setMenuView(View view) {
- setMenuView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- }
- /**
- * Set the menu view to an explicit view.
- *
- * @param view The menu view.
- * @param params Layout parameters for the view.
- */
- public void setMenuView(View view, LayoutParams params) {
- mMenuView = view;
- mMenuContainer.removeAllViews();
- mMenuContainer.addView(view, params);
- }
- /**
- * Returns the menu view.
- *
- * @return The menu view.
- */
- public View getMenuView() {
- return mMenuView;
- }
- /**
- * Set the content from a layout resource.
- *
- * @param layoutResId Resource ID to be inflated.
- */
- public void setContentView(int layoutResId) {
- switch (mDragMode) {
- case MenuDrawer.MENU_DRAG_CONTENT:
- mContentContainer.removeAllViews();
- LayoutInflater.from(getContext()).inflate(layoutResId, mContentContainer, true);
- break;
- case MenuDrawer.MENU_DRAG_WINDOW:
- mActivity.setContentView(layoutResId);
- break;
- }
- }
- /**
- * Set the content to an explicit view.
- *
- * @param view The desired content to display.
- */
- public void setContentView(View view) {
- setContentView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- }
- /**
- * Set the content to an explicit view.
- *
- * @param view The desired content to display.
- * @param params Layout parameters for the view.
- */
- public void setContentView(View view, LayoutParams params) {
- switch (mDragMode) {
- case MenuDrawer.MENU_DRAG_CONTENT:
- mContentContainer.removeAllViews();
- mContentContainer.addView(view, params);
- break;
- case MenuDrawer.MENU_DRAG_WINDOW:
- mActivity.setContentView(view, params);
- break;
- }
- }
- protected void setDrawerState(int state) {
- if (state != mDrawerState) {
- final int oldState = mDrawerState;
- mDrawerState = state;
- if (mOnDrawerStateChangeListener != null) mOnDrawerStateChangeListener.onDrawerStateChange(oldState, state);
- if (DEBUG) logDrawerState(state);
- }
- }
- protected void logDrawerState(int state) {
- switch (state) {
- case STATE_CLOSED:
- Log.d(TAG, "[DrawerState] STATE_CLOSED");
- break;
- case STATE_CLOSING:
- Log.d(TAG, "[DrawerState] STATE_CLOSING");
- break;
- case STATE_DRAGGING:
- Log.d(TAG, "[DrawerState] STATE_DRAGGING");
- break;
- case STATE_OPENING:
- Log.d(TAG, "[DrawerState] STATE_OPENING");
- break;
- case STATE_OPEN:
- Log.d(TAG, "[DrawerState] STATE_OPEN");
- break;
- default:
- Log.d(TAG, "[DrawerState] Unknown: " + state);
- }
- }
- /**
- * Returns the touch mode.
- */
- public abstract int getTouchMode();
- /**
- * Sets the drawer touch mode. Possible values are {@link #TOUCH_MODE_NONE}, {@link #TOUCH_MODE_BEZEL} or
- * {@link #TOUCH_MODE_FULLSCREEN}.
- *
- * @param mode The touch mode.
- */
- public abstract void setTouchMode(int mode);
- /**
- * Sets the size of the touch bezel.
- *
- * @param size The touch bezel size in px.
- */
- public abstract void setTouchBezelSize(int size);
- /**
- * Returns the size of the touch bezel in px.
- */
- public abstract int getTouchBezelSize();
- @Override
- public void postOnAnimation(Runnable action) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- super.postOnAnimation(action);
- } else {
- postDelayed(action, ANIMATION_DELAY);
- }
- }
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- if (mDragMode == MENU_DRAG_WINDOW && mPosition != Position.BOTTOM) {
- mMenuContainer.setPadding(0, insets.top, 0, 0);
- }
- return super.fitSystemWindows(insets);
- }
- protected void dispatchOnDrawerSlide(float openRatio, int offsetPixels) {
- if (mOnDrawerStateChangeListener != null) {
- mOnDrawerStateChangeListener.onDrawerSlide(openRatio, offsetPixels);
- }
- }
- /**
- * Saves the state of the drawer.
- *
- * @return Returns a Parcelable containing the drawer state.
- */
- public final Parcelable saveState() {
- if (mState == null) mState = new Bundle();
- saveState(mState);
- return mState;
- }
- void saveState(Bundle state) {
- // State saving isn't required for subclasses.
- }
- /**
- * Restores the state of the drawer.
- *
- * @param in A parcelable containing the drawer state.
- */
- public void restoreState(Parcelable in) {
- mState = (Bundle) in;
- }
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- SavedState state = new SavedState(superState);
- if (mState == null) mState = new Bundle();
- saveState(mState);
- state.mState = mState;
- return state;
- }
- @Override
- protected void onRestoreInstanceState(Parcelable state) {
- SavedState savedState = (SavedState) state;
- super.onRestoreInstanceState(savedState.getSuperState());
- restoreState(savedState.mState);
- }
- static class SavedState extends BaseSavedState {
- Bundle mState;
- public SavedState(Parcelable superState) {
- super(superState);
- }
- public SavedState(Parcel in) {
- super(in);
- mState = in.readBundle();
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeBundle(mState);
- }
- @SuppressWarnings("UnusedDeclaration")
- public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
- @Override
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
- @Override
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
- }
|