• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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  */
16 package android.transition;
17 
18 import android.animation.Animator;
19 import android.animation.AnimatorListenerAdapter;
20 import android.animation.ObjectAnimator;
21 import android.animation.RectEvaluator;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.content.Context;
25 import android.graphics.Rect;
26 import android.util.AttributeSet;
27 import android.view.View;
28 import android.view.ViewGroup;
29 
30 /**
31  * ChangeClipBounds captures the {@link android.view.View#getClipBounds()} before and after the
32  * scene change and animates those changes during the transition.
33  */
34 public class ChangeClipBounds extends Transition {
35 
36     private static final String TAG = "ChangeTransform";
37 
38     private static final String PROPNAME_CLIP = "android:clipBounds:clip";
39     private static final String PROPNAME_BOUNDS = "android:clipBounds:bounds";
40 
41     private static final String[] sTransitionProperties = {
42             PROPNAME_CLIP,
43     };
44 
ChangeClipBounds()45     public ChangeClipBounds() {}
46 
ChangeClipBounds(Context context, AttributeSet attrs)47     public ChangeClipBounds(Context context, AttributeSet attrs) {
48         super(context, attrs);
49     }
50 
51     @Override
getTransitionProperties()52     public String[] getTransitionProperties() {
53         return sTransitionProperties;
54     }
55 
captureValues(TransitionValues values)56     private void captureValues(TransitionValues values) {
57         View view = values.view;
58         if (view.getVisibility() == View.GONE) {
59             return;
60         }
61 
62         Rect clip = view.getClipBounds();
63         values.values.put(PROPNAME_CLIP, clip);
64         if (clip == null) {
65             Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
66             values.values.put(PROPNAME_BOUNDS, bounds);
67         }
68     }
69 
70     @Override
captureStartValues(TransitionValues transitionValues)71     public void captureStartValues(TransitionValues transitionValues) {
72         captureValues(transitionValues);
73     }
74 
75     @Override
captureEndValues(TransitionValues transitionValues)76     public void captureEndValues(TransitionValues transitionValues) {
77         captureValues(transitionValues);
78     }
79 
80     @Nullable
81     @Override
createAnimator(@onNull final ViewGroup sceneRoot, @Nullable TransitionValues startValues, @Nullable TransitionValues endValues)82     public Animator createAnimator(@NonNull final ViewGroup sceneRoot,
83             @Nullable TransitionValues startValues,
84             @Nullable TransitionValues endValues) {
85         if (startValues == null || endValues == null
86                 || !startValues.values.containsKey(PROPNAME_CLIP)
87                 || !endValues.values.containsKey(PROPNAME_CLIP)) {
88             return null;
89         }
90         Rect start = (Rect) startValues.values.get(PROPNAME_CLIP);
91         Rect end = (Rect) endValues.values.get(PROPNAME_CLIP);
92         boolean endIsNull = end == null;
93         if (start == null && end == null) {
94             return null; // No animation required since there is no clip.
95         }
96 
97         if (start == null) {
98             start = (Rect) startValues.values.get(PROPNAME_BOUNDS);
99         } else if (end == null) {
100             end = (Rect) endValues.values.get(PROPNAME_BOUNDS);
101         }
102         if (start.equals(end)) {
103             return null;
104         }
105 
106         endValues.view.setClipBounds(start);
107         RectEvaluator evaluator = new RectEvaluator(new Rect());
108         ObjectAnimator animator =
109                 ObjectAnimator.ofObject(endValues.view, "clipBounds", evaluator, start, end);
110         if (endIsNull) {
111             final View endView = endValues.view;
112             animator.addListener(new AnimatorListenerAdapter() {
113                 @Override
114                 public void onAnimationEnd(Animator animation) {
115                     endView.setClipBounds(null);
116                 }
117             });
118         }
119         return animator;
120     }
121 }
122