diff options
author | Alan Viverette <alanv@google.com> | 2015-01-29 10:25:34 -0800 |
---|---|---|
committer | Alan Viverette <alanv@google.com> | 2015-01-29 10:25:34 -0800 |
commit | 5435a30ae552391f14009c4459731ae149675b18 (patch) | |
tree | 5582db217741b46b1be1d7a0f72d786a6f87374e /core/java/com | |
parent | 783f28691e27b7b116730fad4f9fd9c083bab283 (diff) | |
download | frameworks_base-5435a30ae552391f14009c4459731ae149675b18.zip frameworks_base-5435a30ae552391f14009c4459731ae149675b18.tar.gz frameworks_base-5435a30ae552391f14009c4459731ae149675b18.tar.bz2 |
Add transition support to PopupWindow
Allows framework-added windows to manually specify surface insets, which
enables us to wrap the popup window's elevated content view with a root
view, which in turn allows us to use the Transition API for popup window
transitions.
Fixes a bug where the root view's render node forced clipping.
Bug: 13211166
Change-Id: I303dfa55a052cdf5d3b1485422529123e3cc867a
Diffstat (limited to 'core/java/com')
-rw-r--r-- | core/java/com/android/internal/transition/EpicenterClipReveal.java | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/core/java/com/android/internal/transition/EpicenterClipReveal.java b/core/java/com/android/internal/transition/EpicenterClipReveal.java new file mode 100644 index 0000000..d8a7f16 --- /dev/null +++ b/core/java/com/android/internal/transition/EpicenterClipReveal.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2015 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.animation.Animator; +import android.animation.ObjectAnimator; +import android.animation.RectEvaluator; +import android.content.Context; +import android.graphics.Rect; +import android.transition.TransitionValues; +import android.transition.Visibility; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +/** + * EpicenterClipReveal captures the {@link View#getClipBounds()} before and + * after the scene change and animates between those and the epicenter bounds + * during a visibility transition. + */ +public class EpicenterClipReveal extends Visibility { + private static final String PROPNAME_CLIP = "android:epicenterReveal:clip"; + private static final String PROPNAME_BOUNDS = "android:epicenterReveal:bounds"; + + public EpicenterClipReveal() {} + + public EpicenterClipReveal(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void captureStartValues(TransitionValues transitionValues) { + super.captureStartValues(transitionValues); + captureValues(transitionValues); + } + + @Override + public void captureEndValues(TransitionValues transitionValues) { + super.captureEndValues(transitionValues); + captureValues(transitionValues); + } + + private void captureValues(TransitionValues values) { + final View view = values.view; + if (view.getVisibility() == View.GONE) { + return; + } + + final Rect clip = view.getClipBounds(); + values.values.put(PROPNAME_CLIP, clip); + + if (clip == null) { + final Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight()); + values.values.put(PROPNAME_BOUNDS, bounds); + } + } + + @Override + public Animator onAppear(ViewGroup sceneRoot, View view, + TransitionValues startValues, TransitionValues endValues) { + if (endValues == null) { + return null; + } + + final Rect start = getEpicenter(); + final Rect end = getBestRect(endValues); + + // Prepare the view. + view.setClipBounds(start); + + return createRectAnimator(view, start, end); + } + + @Override + public Animator onDisappear(ViewGroup sceneRoot, View view, + TransitionValues startValues, TransitionValues endValues) { + if (startValues == null) { + return null; + } + + final Rect start = getBestRect(startValues); + final Rect end = getEpicenter(); + + // Prepare the view. + view.setClipBounds(start); + + return createRectAnimator(view, start, end); + } + + private Rect getBestRect(TransitionValues values) { + final Rect clipRect = (Rect) values.values.get(PROPNAME_CLIP); + if (clipRect == null) { + return (Rect) values.values.get(PROPNAME_BOUNDS); + } + return clipRect; + } + + private Animator createRectAnimator(View view, Rect start, Rect end) { + final RectEvaluator evaluator = new RectEvaluator(new Rect()); + return ObjectAnimator.ofObject(view, "clipBounds", evaluator, start, end); + } +} |