3939import android .content .res .Configuration ;
4040import android .content .res .Resources ;
4141import android .graphics .drawable .Drawable ;
42- import android .os .Build ;
4342import android .os .Handler ;
43+ import android .util .Log ;
4444import android .util .TypedValue ;
4545import android .view .ActionMode ;
4646import android .view .ContextThemeWrapper ;
@@ -110,10 +110,14 @@ public class ActionBarImpl extends ActionBar {
110110
111111 private int mCurWindowVisibility = View .VISIBLE ;
112112
113+ private boolean mHiddenByApp ;
114+ private boolean mHiddenBySystem ;
115+ private boolean mShowingForMode ;
116+
117+ private boolean mNowShowing = true ;
118+
113119 private Animator mCurrentShowAnim ;
114- private Animator mCurrentModeAnim ;
115120 private boolean mShowHideAnimationEnabled ;
116- boolean mWasHiddenBeforeMode ;
117121
118122 final AnimatorListener mHideListener = new AnimatorListenerAdapter () {
119123 @ Override
@@ -129,6 +133,9 @@ public void onAnimationEnd(Animator animation) {
129133 mContainerView .setTransitioning (false );
130134 mCurrentShowAnim = null ;
131135 completeDeferredDestroyActionMode ();
136+ if (mOverlayLayout != null ) {
137+ mOverlayLayout .requestFitSystemWindows ();
138+ }
132139 }
133140 };
134141
@@ -430,16 +437,13 @@ public int getDisplayOptions() {
430437 }
431438
432439 public ActionMode startActionMode (ActionMode .Callback callback ) {
433- boolean wasHidden = false ;
434440 if (mActionMode != null ) {
435- wasHidden = mWasHiddenBeforeMode ;
436441 mActionMode .finish ();
437442 }
438443
439444 mContextView .killMode ();
440445 ActionModeImpl mode = new ActionModeImpl (callback );
441446 if (mode .dispatchOnCreate ()) {
442- mWasHiddenBeforeMode = !isShowing () || wasHidden ;
443447 mode .invalidate ();
444448 mContextView .initForMode (mode );
445449 animateToMode (true );
@@ -584,21 +588,91 @@ public int getHeight() {
584588
585589 @ Override
586590 public void show () {
587- show (true , false );
591+ if (mHiddenByApp ) {
592+ mHiddenByApp = false ;
593+ updateVisibility (false );
594+ }
588595 }
589596
590- public void show (boolean markHiddenBeforeMode , boolean alwaysAnimate ) {
597+ private void showForActionMode () {
598+ if (!mShowingForMode ) {
599+ mShowingForMode = true ;
600+ if (mOverlayLayout != null ) {
601+ mOverlayLayout .setShowingForActionMode (true );
602+ }
603+ updateVisibility (false );
604+ }
605+ }
606+
607+ public void showForSystem () {
608+ if (mHiddenBySystem ) {
609+ mHiddenBySystem = false ;
610+ updateVisibility (true );
611+ }
612+ }
613+
614+ @ Override
615+ public void hide () {
616+ if (!mHiddenByApp ) {
617+ mHiddenByApp = true ;
618+ updateVisibility (false );
619+ }
620+ }
621+
622+ private void hideForActionMode () {
623+ if (mShowingForMode ) {
624+ mShowingForMode = false ;
625+ if (mOverlayLayout != null ) {
626+ mOverlayLayout .setShowingForActionMode (false );
627+ }
628+ updateVisibility (false );
629+ }
630+ }
631+
632+ public void hideForSystem () {
633+ if (!mHiddenBySystem ) {
634+ mHiddenBySystem = true ;
635+ updateVisibility (true );
636+ }
637+ }
638+
639+ private static boolean checkShowingFlags (boolean hiddenByApp , boolean hiddenBySystem ,
640+ boolean showingForMode ) {
641+ if (showingForMode ) {
642+ return true ;
643+ } else if (hiddenByApp || hiddenBySystem ) {
644+ return false ;
645+ } else {
646+ return true ;
647+ }
648+ }
649+
650+ private void updateVisibility (boolean fromSystem ) {
651+ // Based on the current state, should we be hidden or shown?
652+ final boolean shown = checkShowingFlags (mHiddenByApp , mHiddenBySystem ,
653+ mShowingForMode );
654+
655+ if (shown ) {
656+ if (!mNowShowing ) {
657+ mNowShowing = true ;
658+ doShow (fromSystem );
659+ }
660+ } else {
661+ if (mNowShowing ) {
662+ mNowShowing = false ;
663+ doHide (fromSystem );
664+ }
665+ }
666+ }
667+
668+ public void doShow (boolean fromSystem ) {
591669 if (mCurrentShowAnim != null ) {
592670 mCurrentShowAnim .end ();
593671 }
594- if (mTopVisibilityView .getVisibility () == View .VISIBLE ) {
595- if (markHiddenBeforeMode ) mWasHiddenBeforeMode = false ;
596- return ;
597- }
598672 mTopVisibilityView .setVisibility (View .VISIBLE );
599673
600674 if (mCurWindowVisibility == View .VISIBLE && (mShowHideAnimationEnabled
601- || alwaysAnimate )) {
675+ || fromSystem )) {
602676 mTopVisibilityView .setAlpha (0 );
603677 mTopVisibilityView .setTranslationY (-mTopVisibilityView .getHeight ());
604678 AnimatorSet anim = new AnimatorSet ();
@@ -619,6 +693,16 @@ public void show(boolean markHiddenBeforeMode, boolean alwaysAnimate) {
619693 com .android .internal .R .interpolator .decelerate_quad ));
620694 anim .setDuration (mContext .getResources ().getInteger (
621695 com .android .internal .R .integer .config_mediumAnimTime ));
696+ // If this is being shown from the system, add a small delay.
697+ // This is because we will also be animating in the status bar,
698+ // and these two elements can't be done in lock-step. So we give
699+ // a little time for the status bar to start its animation before
700+ // the action bar animates. (This corresponds to the corresponding
701+ // case when hiding, where the status bar has a small delay before
702+ // starting.)
703+ if (fromSystem ) {
704+ anim .setStartDelay (100 );
705+ }
622706 anim .addListener (mShowListener );
623707 mCurrentShowAnim = anim ;
624708 anim .start ();
@@ -627,23 +711,18 @@ public void show(boolean markHiddenBeforeMode, boolean alwaysAnimate) {
627711 mContainerView .setTranslationY (0 );
628712 mShowListener .onAnimationEnd (null );
629713 }
714+ if (mOverlayLayout != null ) {
715+ mOverlayLayout .requestFitSystemWindows ();
716+ }
630717 }
631718
632- @ Override
633- public void hide () {
634- hide (false );
635- }
636-
637- public void hide (boolean alwaysAnimate ) {
719+ public void doHide (boolean fromSystem ) {
638720 if (mCurrentShowAnim != null ) {
639721 mCurrentShowAnim .end ();
640722 }
641- if (mTopVisibilityView .getVisibility () == View .GONE ) {
642- return ;
643- }
644723
645724 if (mCurWindowVisibility == View .VISIBLE && (mShowHideAnimationEnabled
646- || alwaysAnimate )) {
725+ || fromSystem )) {
647726 mTopVisibilityView .setAlpha (1 );
648727 mContainerView .setTransitioning (true );
649728 AnimatorSet anim = new AnimatorSet ();
@@ -673,15 +752,18 @@ public void hide(boolean alwaysAnimate) {
673752 }
674753
675754 public boolean isShowing () {
676- return mTopVisibilityView .getVisibility () == View .VISIBLE ;
755+ return mNowShowing ;
756+ }
757+
758+ public boolean isSystemShowing () {
759+ return !mHiddenBySystem ;
677760 }
678761
679762 void animateToMode (boolean toActionMode ) {
680763 if (toActionMode ) {
681- show (false , false );
682- }
683- if (mCurrentModeAnim != null ) {
684- mCurrentModeAnim .end ();
764+ showForActionMode ();
765+ } else {
766+ hideForActionMode ();
685767 }
686768
687769 mActionView .animateToVisibility (toActionMode ? View .GONE : View .VISIBLE );
@@ -740,11 +822,13 @@ public void finish() {
740822 return ;
741823 }
742824
743- // If we were hidden before the mode was shown, defer the onDestroy
744- // callback until the animation is finished and associated relayout
745- // is about to happen. This lets apps better anticipate visibility
746- // and layout behavior.
747- if (mWasHiddenBeforeMode ) {
825+ // If this change in state is going to cause the action bar
826+ // to be hidden, defer the onDestroy callback until the animation
827+ // is finished and associated relayout is about to happen. This lets
828+ // apps better anticipate visibility and layout behavior.
829+ if (!checkShowingFlags (mHiddenByApp , mHiddenBySystem , false )) {
830+ // With the current state but the action bar hidden, our
831+ // overall showing state is going to be false.
748832 mDeferredDestroyActionMode = this ;
749833 mDeferredModeDestroyCallback = mCallback ;
750834 } else {
@@ -758,10 +842,6 @@ public void finish() {
758842 mActionView .sendAccessibilityEvent (AccessibilityEvent .TYPE_WINDOW_STATE_CHANGED );
759843
760844 mActionMode = null ;
761-
762- if (mWasHiddenBeforeMode ) {
763- hide ();
764- }
765845 }
766846
767847 @ Override
0 commit comments