1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
/*
* 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 android.transition;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
/**
* This transition tracks changes to the visibility of target views in the
* start and end scenes and fades views in or out when they become visible
* or non-visible. Visibility is determined by both the
* {@link View#setVisibility(int)} state of the view as well as whether it
* is parented in the current view hierarchy.
*
* <p>The ability of this transition to fade out a particular view, and the
* way that that fading operation takes place, is based on
* the situation of the view in the view hierarchy. For example, if a view was
* simply removed from its parent, then the view will be added into a {@link
* android.view.ViewGroupOverlay} while fading. If a visible view is
* changed to be {@link View#GONE} or {@link View#INVISIBLE}, then the
* visibility will be changed to {@link View#VISIBLE} for the duration of
* the animation. However, if a view is in a hierarchy which is also altering
* its visibility, the situation can be more complicated. In general, if a
* view that is no longer in the hierarchy in the end scene still has a
* parent (so its parent hierarchy was removed, but it was not removed from
* its parent), then it will be left alone to avoid side-effects from
* improperly removing it from its parent. The only exception to this is if
* the previous {@link Scene} was
* {@link Scene#getSceneForLayout(android.view.ViewGroup, int, android.content.Context)
* created from a layout resource file}, then it is considered safe to un-parent
* the starting scene view in order to fade it out.</p>
*
* <p>A Fade transition can be described in a resource file by using the
* tag <code>fade</code>, along with the standard
* attributes of {@link android.R.styleable#Fade} and
* {@link android.R.styleable#Transition}.</p>
*/
public class Fade extends Visibility {
private static boolean DBG = Transition.DBG && false;
private static final String LOG_TAG = "Fade";
/**
* Fading mode used in {@link #Fade(int)} to make the transition
* operate on targets that are appearing. Maybe be combined with
* {@link #OUT} to fade both in and out. Equivalent to
* {@link Visibility#IN}.
*/
public static final int IN = Visibility.IN;
/**
* Fading mode used in {@link #Fade(int)} to make the transition
* operate on targets that are disappearing. Maybe be combined with
* {@link #IN} to fade both in and out. Equivalent to
* {@link Visibility#OUT}.
*/
public static final int OUT = Visibility.OUT;
/**
* Constructs a Fade transition that will fade targets in and out.
*/
public Fade() {
}
/**
* Constructs a Fade transition that will fade targets in
* and/or out, according to the value of fadingMode.
*
* @param fadingMode The behavior of this transition, a combination of
* {@link #IN} and {@link #OUT}.
*/
public Fade(int fadingMode) {
setMode(fadingMode);
}
/**
* Utility method to handle creating and running the Animator.
*/
private Animator createAnimation(View view, float startAlpha, float endAlpha) {
if (startAlpha == endAlpha) {
return null;
}
view.setTransitionAlpha(startAlpha);
final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "transitionAlpha", endAlpha);
if (DBG) {
Log.d(LOG_TAG, "Created animator " + anim);
}
FadeAnimatorListener listener = new FadeAnimatorListener(view);
anim.addListener(listener);
anim.addPauseListener(listener);
return anim;
}
@Override
public Animator onAppear(ViewGroup sceneRoot, View view,
TransitionValues startValues,
TransitionValues endValues) {
if (DBG) {
View startView = (startValues != null) ? startValues.view : null;
Log.d(LOG_TAG, "Fade.onAppear: startView, startVis, endView, endVis = " +
startView + ", " + view);
}
return createAnimation(view, 0, 1);
}
@Override
public Animator onDisappear(ViewGroup sceneRoot, final View view, TransitionValues startValues,
TransitionValues endValues) {
return createAnimation(view, 1, 0);
}
private static class FadeAnimatorListener extends AnimatorListenerAdapter {
private final View mView;
private boolean mCanceled = false;
private float mPausedAlpha = -1;
public FadeAnimatorListener(View view) {
mView = view;
}
@Override
public void onAnimationCancel(Animator animator) {
mCanceled = true;
if (mPausedAlpha >= 0) {
mView.setTransitionAlpha(mPausedAlpha);
}
}
@Override
public void onAnimationEnd(Animator animator) {
if (!mCanceled) {
mView.setTransitionAlpha(1);
}
}
@Override
public void onAnimationPause(Animator animator) {
mPausedAlpha = mView.getTransitionAlpha();
mView.setTransitionAlpha(1);
}
@Override
public void onAnimationResume(Animator animator) {
mView.setTransitionAlpha(mPausedAlpha);
}
}
}
|