diff options
author | Chet Haase <chet@google.com> | 2015-04-09 14:31:25 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2015-04-14 14:09:26 +0000 |
commit | 575217fc3da38357f1d5e322bf1c7a07b909ef2a (patch) | |
tree | 6571b525c6d1e936493a5e63838ade128647a917 | |
parent | de77be631184ff1204017c3d8996d7c71aa5cf02 (diff) | |
download | frameworks_base-575217fc3da38357f1d5e322bf1c7a07b909ef2a.zip frameworks_base-575217fc3da38357f1d5e322bf1c7a07b909ef2a.tar.gz frameworks_base-575217fc3da38357f1d5e322bf1c7a07b909ef2a.tar.bz2 |
Make ActionBar animations work correctly
Previous ActionBar animations didn't handle configuration changes
or other situations in which the view would get detached. listeners
would stay on the view and would attempt to do something nonsensical
in the new window. This new approach removes listeners on window
detach to avoid this problem.
Issue #20125407 Settings Crashes when changing orientation of device
Change-Id: I0b3bbd0f6fc23cdb4cbd646b0d2772d72d3d795d
-rw-r--r-- | core/java/android/widget/ActionMenuPresenter.java | 67 | ||||
-rw-r--r-- | core/java/com/android/internal/transition/ActionBarTransition.java | 58 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/ActionBarView.java | 11 | ||||
-rw-r--r-- | preloaded-classes | 1 |
4 files changed, 45 insertions, 92 deletions
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java index f951dc2..e0b0e1f 100644 --- a/core/java/android/widget/ActionMenuPresenter.java +++ b/core/java/android/widget/ActionMenuPresenter.java @@ -40,7 +40,6 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ListPopupWindow.ForwardingListener; -import com.android.internal.transition.ActionBarTransition; import com.android.internal.view.ActionBarPolicy; import com.android.internal.view.menu.ActionMenuItemView; import com.android.internal.view.menu.BaseMenuPresenter; @@ -99,7 +98,30 @@ public class ActionMenuPresenter extends BaseMenuPresenter // The list of currently running animations on menu items. private List<ItemAnimationInfo> mRunningItemAnimations = new ArrayList<ItemAnimationInfo>(); + private ViewTreeObserver.OnPreDrawListener mItemAnimationPreDrawListener = + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + computeMenuItemAnimationInfo(false); + ((View) mMenuView).getViewTreeObserver().removeOnPreDrawListener(this); + runItemAnimations(); + return true; + } + }; + private View.OnAttachStateChangeListener mAttachStateChangeListener = + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + } + @Override + public void onViewDetachedFromWindow(View v) { + ((View) mMenuView).getViewTreeObserver().removeOnPreDrawListener( + mItemAnimationPreDrawListener); + mPreLayoutItems.clear(); + mPostLayoutItems.clear(); + } + }; public ActionMenuPresenter(Context context) { @@ -177,8 +199,15 @@ public class ActionMenuPresenter extends BaseMenuPresenter @Override public MenuView getMenuView(ViewGroup root) { + MenuView oldMenuView = mMenuView; MenuView result = super.getMenuView(root); - ((ActionMenuView) result).setPresenter(this); + if (oldMenuView != result) { + ((ActionMenuView) result).setPresenter(this); + if (oldMenuView != null) { + ((View) oldMenuView).removeOnAttachStateChangeListener(mAttachStateChangeListener); + } + ((View) result).addOnAttachStateChangeListener(mAttachStateChangeListener); + } return result; } @@ -226,11 +255,11 @@ public class ActionMenuPresenter extends BaseMenuPresenter * into the MenuItemLayoutInfo structure to store the appropriate position values. */ private void computeMenuItemAnimationInfo(boolean preLayout) { - final ViewGroup menuViewParent = (ViewGroup) mMenuView; - final int count = menuViewParent.getChildCount(); + final ViewGroup menuView = (ViewGroup) mMenuView; + final int count = menuView.getChildCount(); SparseArray items = preLayout ? mPreLayoutItems : mPostLayoutItems; for (int i = 0; i < count; ++i) { - View child = menuViewParent.getChildAt(i); + View child = menuView.getChildAt(i); final int id = child.getId(); if (id > 0 && child.getWidth() != 0 && child.getHeight() != 0) { MenuItemLayoutInfo info = new MenuItemLayoutInfo(child, preLayout); @@ -377,28 +406,16 @@ public class ActionMenuPresenter extends BaseMenuPresenter * which is then fed into runItemAnimations() */ private void setupItemAnimations() { - final ViewGroup menuViewParent = (ViewGroup) mMenuView; computeMenuItemAnimationInfo(true); - final ViewTreeObserver observer = menuViewParent.getViewTreeObserver(); - if (observer != null) { - observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - computeMenuItemAnimationInfo(false); - observer.removeOnPreDrawListener(this); - runItemAnimations(); - return true; - } - }); - } + ((View) mMenuView).getViewTreeObserver(). + addOnPreDrawListener(mItemAnimationPreDrawListener); } @Override public void updateMenuView(boolean cleared) { final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent(); if (menuViewParent != null) { -// setupItemAnimations(); - ActionBarTransition.beginDelayedTransition(menuViewParent); + setupItemAnimations(); } super.updateMenuView(cleared); @@ -736,8 +753,14 @@ public class ActionMenuPresenter extends BaseMenuPresenter } public void setMenuView(ActionMenuView menuView) { - mMenuView = menuView; - menuView.initialize(mMenu); + if (menuView != mMenuView) { + if (mMenuView != null) { + ((View) mMenuView).removeOnAttachStateChangeListener(mAttachStateChangeListener); + } + mMenuView = menuView; + menuView.initialize(mMenu); + menuView.addOnAttachStateChangeListener(mAttachStateChangeListener); + } } public void setOverflowTintList(ColorStateList tint) { diff --git a/core/java/com/android/internal/transition/ActionBarTransition.java b/core/java/com/android/internal/transition/ActionBarTransition.java deleted file mode 100644 index c1065e7..0000000 --- a/core/java/com/android/internal/transition/ActionBarTransition.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 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 com.android.internal.transition; - -import android.transition.ChangeBounds; -import android.transition.Fade; -import android.transition.ChangeText; -import android.transition.Transition; -import android.transition.TransitionManager; -import android.transition.TransitionSet; -import android.view.ViewGroup; - -public class ActionBarTransition { - - private static boolean TRANSITIONS_ENABLED = false; - - private static final int TRANSITION_DURATION = 120; // ms - - private static final Transition sTransition; - - static { - if (TRANSITIONS_ENABLED) { - final ChangeText tc = new ChangeText(); - tc.setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN); - final TransitionSet inner = new TransitionSet(); - inner.addTransition(tc).addTransition(new ChangeBounds()); - final TransitionSet tg = new TransitionSet(); - tg.addTransition(new Fade(Fade.OUT)).addTransition(inner). - addTransition(new Fade(Fade.IN)); - tg.setOrdering(TransitionSet.ORDERING_SEQUENTIAL); - tg.setDuration(TRANSITION_DURATION); - sTransition = tg; - } else { - sTransition = null; - } - } - - public static void beginDelayedTransition(ViewGroup sceneRoot) { - if (TRANSITIONS_ENABLED) { - TransitionManager.beginDelayedTransition(sceneRoot, sTransition); - } - } -} diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 88436f8..6b781c3 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -49,7 +49,6 @@ import android.widget.Spinner; import android.widget.SpinnerAdapter; import android.widget.TextView; import com.android.internal.R; -import com.android.internal.transition.ActionBarTransition; import com.android.internal.view.menu.ActionMenuItem; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuItemImpl; @@ -459,9 +458,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { public void setCustomView(View view) { final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0; - if (showCustom) { - ActionBarTransition.beginDelayedTransition(this); - } if (mCustomNavView != null && showCustom) { removeView(mCustomNavView); } @@ -499,7 +495,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { } private void setTitleImpl(CharSequence title) { - ActionBarTransition.beginDelayedTransition(this); mTitle = title; if (mTitleView != null) { mTitleView.setText(title); @@ -519,7 +514,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { } public void setSubtitle(CharSequence subtitle) { - ActionBarTransition.beginDelayedTransition(this); mSubtitle = subtitle; if (mSubtitleView != null) { mSubtitleView.setText(subtitle); @@ -604,7 +598,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { mDisplayOptions = options; if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) { - ActionBarTransition.beginDelayedTransition(this); if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) { final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0; @@ -706,7 +699,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { public void setNavigationMode(int mode) { final int oldMode = mNavigationMode; if (mode != oldMode) { - ActionBarTransition.beginDelayedTransition(this); switch (oldMode) { case ActionBar.NAVIGATION_MODE_LIST: if (mListNavLayout != null) { @@ -836,7 +828,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { } } - ActionBarTransition.beginDelayedTransition(this); mUpGoerFive.addView(mTitleLayout); if (mExpandedActionView != null || (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) { @@ -1659,7 +1650,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { @Override public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { - ActionBarTransition.beginDelayedTransition(ActionBarView.this); mExpandedActionView = item.getActionView(); mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(getResources())); @@ -1688,7 +1678,6 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar { @Override public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { - ActionBarTransition.beginDelayedTransition(ActionBarView.this); // Do this before detaching the actionview from the hierarchy, in case // it needs to dismiss the soft keyboard, etc. diff --git a/preloaded-classes b/preloaded-classes index 151766f..86bd5c9 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -1791,7 +1791,6 @@ com.android.internal.telephony.ITelephonyRegistry com.android.internal.telephony.ITelephonyRegistry$Stub com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy com.android.internal.telephony.PhoneConstants$State -com.android.internal.transition.ActionBarTransition com.android.internal.util.ArrayUtils com.android.internal.util.FastPrintWriter com.android.internal.util.FastPrintWriter$1 |