blob: abb50c1df692e9bc5a96caeeadbef859e4d2b2a8 [file] [log] [blame]
Alan Viverette5435a302015-01-29 10:25:34 -08001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.internal.transition;
17
18import android.animation.Animator;
George Mount3c75db92015-03-05 14:09:33 -080019import android.animation.AnimatorListenerAdapter;
Alan Viverette5435a302015-01-29 10:25:34 -080020import android.animation.ObjectAnimator;
21import android.animation.RectEvaluator;
22import android.content.Context;
23import android.graphics.Rect;
24import android.transition.TransitionValues;
25import android.transition.Visibility;
26import android.util.AttributeSet;
27import android.view.View;
28import android.view.ViewGroup;
29
30/**
31 * EpicenterClipReveal captures the {@link View#getClipBounds()} before and
32 * after the scene change and animates between those and the epicenter bounds
33 * during a visibility transition.
34 */
35public class EpicenterClipReveal extends Visibility {
36 private static final String PROPNAME_CLIP = "android:epicenterReveal:clip";
37 private static final String PROPNAME_BOUNDS = "android:epicenterReveal:bounds";
38
39 public EpicenterClipReveal() {}
40
41 public EpicenterClipReveal(Context context, AttributeSet attrs) {
42 super(context, attrs);
43 }
44
45 @Override
46 public void captureStartValues(TransitionValues transitionValues) {
47 super.captureStartValues(transitionValues);
48 captureValues(transitionValues);
49 }
50
51 @Override
52 public void captureEndValues(TransitionValues transitionValues) {
53 super.captureEndValues(transitionValues);
54 captureValues(transitionValues);
55 }
56
57 private void captureValues(TransitionValues values) {
58 final View view = values.view;
59 if (view.getVisibility() == View.GONE) {
60 return;
61 }
62
63 final Rect clip = view.getClipBounds();
64 values.values.put(PROPNAME_CLIP, clip);
65
66 if (clip == null) {
67 final Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
68 values.values.put(PROPNAME_BOUNDS, bounds);
69 }
70 }
71
72 @Override
73 public Animator onAppear(ViewGroup sceneRoot, View view,
74 TransitionValues startValues, TransitionValues endValues) {
75 if (endValues == null) {
76 return null;
77 }
78
Alan Viverette5435a302015-01-29 10:25:34 -080079 final Rect end = getBestRect(endValues);
George Mount3c75db92015-03-05 14:09:33 -080080 final Rect start = getEpicenterOrCenter(end);
Alan Viverette5435a302015-01-29 10:25:34 -080081
82 // Prepare the view.
83 view.setClipBounds(start);
84
George Mount3c75db92015-03-05 14:09:33 -080085 return createRectAnimator(view, start, end, endValues);
Alan Viverette5435a302015-01-29 10:25:34 -080086 }
87
88 @Override
89 public Animator onDisappear(ViewGroup sceneRoot, View view,
90 TransitionValues startValues, TransitionValues endValues) {
91 if (startValues == null) {
92 return null;
93 }
94
95 final Rect start = getBestRect(startValues);
George Mount3c75db92015-03-05 14:09:33 -080096 final Rect end = getEpicenterOrCenter(start);
Alan Viverette5435a302015-01-29 10:25:34 -080097
98 // Prepare the view.
99 view.setClipBounds(start);
100
George Mount3c75db92015-03-05 14:09:33 -0800101 return createRectAnimator(view, start, end, endValues);
102 }
103
104 private Rect getEpicenterOrCenter(Rect bestRect) {
105 final Rect epicenter = getEpicenter();
106 if (epicenter != null) {
107 return epicenter;
108 }
109
110 int centerX = bestRect.centerX();
111 int centerY = bestRect.centerY();
112 return new Rect(centerX, centerY, centerX, centerY);
Alan Viverette5435a302015-01-29 10:25:34 -0800113 }
114
115 private Rect getBestRect(TransitionValues values) {
116 final Rect clipRect = (Rect) values.values.get(PROPNAME_CLIP);
117 if (clipRect == null) {
118 return (Rect) values.values.get(PROPNAME_BOUNDS);
119 }
120 return clipRect;
121 }
122
George Mount3c75db92015-03-05 14:09:33 -0800123 private Animator createRectAnimator(final View view, Rect start, Rect end,
124 TransitionValues endValues) {
125 final Rect terminalClip = (Rect) endValues.values.get(PROPNAME_CLIP);
Alan Viverette5435a302015-01-29 10:25:34 -0800126 final RectEvaluator evaluator = new RectEvaluator(new Rect());
George Mount3c75db92015-03-05 14:09:33 -0800127 ObjectAnimator anim = ObjectAnimator.ofObject(view, "clipBounds", evaluator, start, end);
128 anim.addListener(new AnimatorListenerAdapter() {
129 @Override
130 public void onAnimationEnd(Animator animation) {
131 view.setClipBounds(terminalClip);
132 }
133 });
134 return anim;
Alan Viverette5435a302015-01-29 10:25:34 -0800135 }
136}