diff options
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index e0a30ad..3b026d2 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -19,6 +19,9 @@ package android.app; import android.animation.Animator; import android.animation.AnimatorInflater; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; @@ -403,6 +406,44 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate static final String VIEW_STATE_TAG = "android:view_state"; static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint"; + static class AnimateOnHWLayerIfNeededListener implements Animator.AnimatorListener { + private boolean mShouldRunOnHWLayer = false; + private View mView; + public AnimateOnHWLayerIfNeededListener(final View v) { + if (v == null) { + return; + } + mView = v; + } + + @Override + public void onAnimationStart(Animator animation) { + mShouldRunOnHWLayer = shouldRunOnHWLayer(mView, animation); + if (mShouldRunOnHWLayer) { + mView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mShouldRunOnHWLayer) { + mView.setLayerType(View.LAYER_TYPE_NONE, null); + } + mView = null; + animation.removeListener(this); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + } + ArrayList<Runnable> mPendingActions; Runnable[] mTmpActions; boolean mExecutingActions; @@ -467,6 +508,50 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate throw ex; } + static boolean modifiesAlpha(Animator anim) { + if (anim == null) { + return false; + } + if (anim instanceof ValueAnimator) { + ValueAnimator valueAnim = (ValueAnimator) anim; + PropertyValuesHolder[] values = valueAnim.getValues(); + for (int i = 0; i < values.length; i++) { + if (("alpha").equals(values[i].getPropertyName())) { + return true; + } + } + } else if (anim instanceof AnimatorSet) { + List<Animator> animList = ((AnimatorSet) anim).getChildAnimations(); + for (int i = 0; i < animList.size(); i++) { + if (modifiesAlpha(animList.get(i))) { + return true; + } + } + } + return false; + } + + static boolean shouldRunOnHWLayer(View v, Animator anim) { + if (v == null || anim == null) { + return false; + } + return v.getLayerType() == View.LAYER_TYPE_NONE + && v.hasOverlappingRendering() + && modifiesAlpha(anim); + } + + /** + * Sets the to be animated view on hardware layer during the animation. + */ + private void setHWLayerAnimListenerIfAlpha(final View v, Animator anim) { + if (v == null || anim == null) { + return; + } + if (shouldRunOnHWLayer(v, anim)) { + anim.addListener(new AnimateOnHWLayerIfNeededListener(v)); + } + } + @Override public FragmentTransaction beginTransaction() { return new BackStackRecord(this); @@ -894,6 +979,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate transitionStyle); if (anim != null) { anim.setTarget(f.mView); + setHWLayerAnimListenerIfAlpha(f.mView, anim); anim.start(); } container.addView(f.mView); @@ -975,6 +1061,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } }); anim.setTarget(f.mView); + setHWLayerAnimListenerIfAlpha(f.mView, anim); anim.start(); } @@ -1188,6 +1275,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } } }); + setHWLayerAnimListenerIfAlpha(finalFragment.mView, anim); anim.start(); } else { fragment.mView.setVisibility(View.GONE); @@ -1209,6 +1297,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate transitionStyle); if (anim != null) { anim.setTarget(fragment.mView); + setHWLayerAnimListenerIfAlpha(fragment.mView, anim); anim.start(); } fragment.mView.setVisibility(View.VISIBLE); |
