blob: 1629726cadd572f411c6507b59493270476bc00d [file] [log] [blame]
Chet Haasefaebd8f2012-05-18 14:17:57 -07001/*
2 * Copyright (C) 2013 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 */
Chet Haase6ebe3de2013-06-17 16:50:50 -070016
Chet Haased82c8ac2013-08-26 14:20:16 -070017package android.transition;
Chet Haasefaebd8f2012-05-18 14:17:57 -070018
George Mountecd857b2014-06-19 07:51:08 -070019import com.android.internal.R;
20
Chet Haasefaebd8f2012-05-18 14:17:57 -070021import android.animation.Animator;
George Mountd6107a32014-03-10 16:51:16 -070022import android.animation.AnimatorListenerAdapter;
George Mountecd857b2014-06-19 07:51:08 -070023import android.content.Context;
24import android.content.res.TypedArray;
George Mountd4c3c912014-06-09 12:31:34 -070025import android.graphics.Bitmap;
26import android.graphics.Canvas;
27import android.graphics.drawable.BitmapDrawable;
George Mountecd857b2014-06-19 07:51:08 -070028import android.util.AttributeSet;
Chet Haasefaebd8f2012-05-18 14:17:57 -070029import android.view.View;
30import android.view.ViewGroup;
Chet Haasefaebd8f2012-05-18 14:17:57 -070031/**
32 * This transition tracks changes to the visibility of target views in the
33 * start and end scenes. Visibility is determined not just by the
34 * {@link View#setVisibility(int)} state of views, but also whether
35 * views exist in the current view hierarchy. The class is intended to be a
36 * utility for subclasses such as {@link Fade}, which use this visibility
37 * information to determine the specific animations to run when visibility
Chet Haase35a457a2013-08-26 07:34:12 -070038 * changes occur. Subclasses should implement one or both of the methods
Chet Haased82c8ac2013-08-26 14:20:16 -070039 * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)},
George Mountd6107a32014-03-10 16:51:16 -070040 * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)} or
41 * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)},
42 * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
Chet Haasefaebd8f2012-05-18 14:17:57 -070043 */
44public abstract class Visibility extends Transition {
45
46 private static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
47 private static final String PROPNAME_PARENT = "android:visibility:parent";
George Mountd6107a32014-03-10 16:51:16 -070048 private static final String PROPNAME_SCREEN_LOCATION = "android:visibility:screenLocation";
49
George Mount18ab7992014-06-25 17:04:51 -070050 /**
51 * Mode used in {@link #setMode(int)} to make the transition
52 * operate on targets that are appearing. Maybe be combined with
53 * {@link #OUT} to target Visibility changes both in and out.
54 */
55 public static final int IN = 0x1;
56
57 /**
58 * Mode used in {@link #setMode(int)} to make the transition
59 * operate on targets that are disappearing. Maybe be combined with
60 * {@link #IN} to target Visibility changes both in and out.
61 */
62 public static final int OUT = 0x2;
63
Chet Haaseaf78bdd2013-08-27 16:06:26 -070064 private static final String[] sTransitionProperties = {
Chet Haase199acdf2013-07-24 18:40:55 -070065 PROPNAME_VISIBILITY,
66 PROPNAME_PARENT,
George Mountd6107a32014-03-10 16:51:16 -070067 PROPNAME_SCREEN_LOCATION,
Chet Haase199acdf2013-07-24 18:40:55 -070068 };
Chet Haasefaebd8f2012-05-18 14:17:57 -070069
Chet Haase6ebe3de2013-06-17 16:50:50 -070070 private static class VisibilityInfo {
71 boolean visibilityChange;
72 boolean fadeIn;
73 int startVisibility;
74 int endVisibility;
Chet Haase35a457a2013-08-26 07:34:12 -070075 ViewGroup startParent;
76 ViewGroup endParent;
Chet Haase6ebe3de2013-06-17 16:50:50 -070077 }
78
George Mount18ab7992014-06-25 17:04:51 -070079 private int mMode = IN | OUT;
80
George Mountecd857b2014-06-19 07:51:08 -070081 public Visibility() {}
82
83 public Visibility(Context context, AttributeSet attrs) {
84 super(context, attrs);
85 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition);
86 int mode = a.getInt(R.styleable.VisibilityTransition_visibilityMode, 0);
87 a.recycle();
88 if (mode != 0) {
89 setMode(mode);
90 }
91 }
92
George Mount18ab7992014-06-25 17:04:51 -070093 /**
94 * Changes the transition to support appearing and/or disappearing Views, depending
95 * on <code>mode</code>.
96 *
97 * @param mode The behavior supported by this transition, a combination of
98 * {@link #IN} and {@link #OUT}.
George Mountecd857b2014-06-19 07:51:08 -070099 * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
George Mount18ab7992014-06-25 17:04:51 -0700100 */
101 public void setMode(int mode) {
102 if ((mode & ~(IN | OUT)) != 0) {
103 throw new IllegalArgumentException("Only IN and OUT flags are allowed");
104 }
105 mMode = mode;
106 }
107
George Mountecd857b2014-06-19 07:51:08 -0700108 /**
109 * Returns whether appearing and/or disappearing Views are supported.
110 *
111 * Returns whether appearing and/or disappearing Views are supported. A combination of
112 * {@link #IN} and {@link #OUT}.
113 * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
114 */
115 public int getMode() {
116 return mMode;
117 }
118
Chet Haasefaebd8f2012-05-18 14:17:57 -0700119 @Override
Chet Haase199acdf2013-07-24 18:40:55 -0700120 public String[] getTransitionProperties() {
121 return sTransitionProperties;
122 }
123
Chet Haased82c8ac2013-08-26 14:20:16 -0700124 private void captureValues(TransitionValues transitionValues) {
125 int visibility = transitionValues.view.getVisibility();
126 transitionValues.values.put(PROPNAME_VISIBILITY, visibility);
127 transitionValues.values.put(PROPNAME_PARENT, transitionValues.view.getParent());
George Mountd6107a32014-03-10 16:51:16 -0700128 int[] loc = new int[2];
129 transitionValues.view.getLocationOnScreen(loc);
130 transitionValues.values.put(PROPNAME_SCREEN_LOCATION, loc);
Chet Haased82c8ac2013-08-26 14:20:16 -0700131 }
132
Chet Haase199acdf2013-07-24 18:40:55 -0700133 @Override
Chet Haased82c8ac2013-08-26 14:20:16 -0700134 public void captureStartValues(TransitionValues transitionValues) {
135 captureValues(transitionValues);
136 }
137
138 @Override
139 public void captureEndValues(TransitionValues transitionValues) {
140 captureValues(transitionValues);
Chet Haasefaebd8f2012-05-18 14:17:57 -0700141 }
142
Chet Haase199acdf2013-07-24 18:40:55 -0700143 /**
144 * Returns whether the view is 'visible' according to the given values
145 * object. This is determined by testing the same properties in the values
146 * object that are used to determine whether the object is appearing or
147 * disappearing in the {@link
Chet Haased82c8ac2013-08-26 14:20:16 -0700148 * Transition#createAnimator(ViewGroup, TransitionValues, TransitionValues)}
Chet Haase199acdf2013-07-24 18:40:55 -0700149 * method. This method can be called by, for example, subclasses that want
150 * to know whether the object is visible in the same way that Visibility
151 * determines it for the actual animation.
152 *
153 * @param values The TransitionValues object that holds the information by
154 * which visibility is determined.
155 * @return True if the view reference by <code>values</code> is visible,
156 * false otherwise.
157 */
158 public boolean isVisible(TransitionValues values) {
159 if (values == null) {
160 return false;
161 }
162 int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
163 View parent = (View) values.values.get(PROPNAME_PARENT);
164
165 return visibility == View.VISIBLE && parent != null;
166 }
167
Chet Haase6ebe3de2013-06-17 16:50:50 -0700168 private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues,
Chet Haasefaebd8f2012-05-18 14:17:57 -0700169 TransitionValues endValues) {
Chet Haase7660d122013-09-13 13:29:31 -0700170 final VisibilityInfo visInfo = new VisibilityInfo();
Chet Haase6ebe3de2013-06-17 16:50:50 -0700171 visInfo.visibilityChange = false;
172 visInfo.fadeIn = false;
George Mount31a21722014-03-24 17:44:36 -0700173 if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700174 visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
Chet Haase35a457a2013-08-26 07:34:12 -0700175 visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
Chet Haasefaebd8f2012-05-18 14:17:57 -0700176 } else {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700177 visInfo.startVisibility = -1;
178 visInfo.startParent = null;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700179 }
George Mount31a21722014-03-24 17:44:36 -0700180 if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700181 visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
Chet Haase35a457a2013-08-26 07:34:12 -0700182 visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
Chet Haasefaebd8f2012-05-18 14:17:57 -0700183 } else {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700184 visInfo.endVisibility = -1;
185 visInfo.endParent = null;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700186 }
Chet Haasefaebd8f2012-05-18 14:17:57 -0700187 if (startValues != null && endValues != null) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700188 if (visInfo.startVisibility == visInfo.endVisibility &&
189 visInfo.startParent == visInfo.endParent) {
190 return visInfo;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700191 } else {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700192 if (visInfo.startVisibility != visInfo.endVisibility) {
193 if (visInfo.startVisibility == View.VISIBLE) {
194 visInfo.fadeIn = false;
195 visInfo.visibilityChange = true;
196 } else if (visInfo.endVisibility == View.VISIBLE) {
197 visInfo.fadeIn = true;
198 visInfo.visibilityChange = true;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700199 }
200 // no visibilityChange if going between INVISIBLE and GONE
Chet Haase6ebe3de2013-06-17 16:50:50 -0700201 } else if (visInfo.startParent != visInfo.endParent) {
202 if (visInfo.endParent == null) {
203 visInfo.fadeIn = false;
204 visInfo.visibilityChange = true;
205 } else if (visInfo.startParent == null) {
206 visInfo.fadeIn = true;
207 visInfo.visibilityChange = true;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700208 }
209 }
210 }
211 }
212 if (startValues == null) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700213 visInfo.fadeIn = true;
214 visInfo.visibilityChange = true;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700215 } else if (endValues == null) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700216 visInfo.fadeIn = false;
217 visInfo.visibilityChange = true;
Chet Haasefaebd8f2012-05-18 14:17:57 -0700218 }
Chet Haase6ebe3de2013-06-17 16:50:50 -0700219 return visInfo;
220 }
221
222 @Override
Chet Haased82c8ac2013-08-26 14:20:16 -0700223 public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
Chet Haase6ebe3de2013-06-17 16:50:50 -0700224 TransitionValues endValues) {
225 VisibilityInfo visInfo = getVisibilityChangeInfo(startValues, endValues);
George Mount30da61d2014-05-09 13:17:52 -0700226 if (visInfo.visibilityChange
227 && (visInfo.startParent != null || visInfo.endParent != null)) {
228 if (visInfo.fadeIn) {
229 return onAppear(sceneRoot, startValues, visInfo.startVisibility,
230 endValues, visInfo.endVisibility);
231 } else {
232 return onDisappear(sceneRoot, startValues, visInfo.startVisibility,
233 endValues, visInfo.endVisibility
234 );
Chet Haasefaebd8f2012-05-18 14:17:57 -0700235 }
Chet Haasefaebd8f2012-05-18 14:17:57 -0700236 }
Chet Haasefaebd8f2012-05-18 14:17:57 -0700237 return null;
238 }
239
240 /**
George Mountd6107a32014-03-10 16:51:16 -0700241 * The default implementation of this method calls
242 * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
243 * Subclasses should override this method or
244 * {@link #onAppear(ViewGroup, View, TransitionValues, TransitionValues)}.
245 * if they need to create an Animator when targets appear.
Chet Haased82c8ac2013-08-26 14:20:16 -0700246 * The method should only be called by the Visibility class; it is
247 * not intended to be called from external classes.
Chet Haasefaebd8f2012-05-18 14:17:57 -0700248 *
Chet Haased82c8ac2013-08-26 14:20:16 -0700249 * @param sceneRoot The root of the transition hierarchy
250 * @param startValues The target values in the start scene
251 * @param startVisibility The target visibility in the start scene
252 * @param endValues The target values in the end scene
253 * @param endVisibility The target visibility in the end scene
254 * @return An Animator to be started at the appropriate time in the
255 * overall transition for this scene change. A null value means no animation
256 * should be run.
Chet Haasefaebd8f2012-05-18 14:17:57 -0700257 */
Chet Haased82c8ac2013-08-26 14:20:16 -0700258 public Animator onAppear(ViewGroup sceneRoot,
Chet Haase6ebe3de2013-06-17 16:50:50 -0700259 TransitionValues startValues, int startVisibility,
260 TransitionValues endValues, int endVisibility) {
George Mount18ab7992014-06-25 17:04:51 -0700261 if ((mMode & IN) != IN || endValues == null) {
262 return null;
263 }
George Mountd6107a32014-03-10 16:51:16 -0700264 return onAppear(sceneRoot, endValues.view, startValues, endValues);
265 }
266
267 /**
268 * The default implementation of this method returns a null Animator. Subclasses should
269 * override this method to make targets appear with the desired transition. The
270 * method should only be called from
271 * {@link #onAppear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
272 *
273 * @param sceneRoot The root of the transition hierarchy
274 * @param view The View to make appear. This will be in the target scene's View hierarchy and
275 * will be VISIBLE.
276 * @param startValues The target values in the start scene
277 * @param endValues The target values in the end scene
278 * @return An Animator to be started at the appropriate time in the
279 * overall transition for this scene change. A null value means no animation
280 * should be run.
281 */
282 public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
283 TransitionValues endValues) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700284 return null;
285 }
Chet Haasefaebd8f2012-05-18 14:17:57 -0700286
287 /**
George Mountd6107a32014-03-10 16:51:16 -0700288 * Subclasses should override this method or
289 * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}
290 * if they need to create an Animator when targets disappear.
Chet Haased82c8ac2013-08-26 14:20:16 -0700291 * The method should only be called by the Visibility class; it is
292 * not intended to be called from external classes.
George Mountd6107a32014-03-10 16:51:16 -0700293 * <p>
294 * The default implementation of this method attempts to find a View to use to call
295 * {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)},
296 * based on the situation of the View in the View hierarchy. For example,
297 * if a View was simply removed from its parent, then the View will be added
298 * into a {@link android.view.ViewGroupOverlay} and passed as the <code>view</code>
299 * parameter in {@link #onDisappear(ViewGroup, View, TransitionValues, TransitionValues)}.
300 * If a visible View is changed to be {@link View#GONE} or {@link View#INVISIBLE},
301 * then it can be used as the <code>view</code> and the visibility will be changed
302 * to {@link View#VISIBLE} for the duration of the animation. However, if a View
303 * is in a hierarchy which is also altering its visibility, the situation can be
304 * more complicated. In general, if a view that is no longer in the hierarchy in
305 * the end scene still has a parent (so its parent hierarchy was removed, but it
306 * was not removed from its parent), then it will be left alone to avoid side-effects from
307 * improperly removing it from its parent. The only exception to this is if
308 * the previous {@link Scene} was {@link Scene#getSceneForLayout(ViewGroup, int,
309 * android.content.Context) created from a layout resource file}, then it is considered
310 * safe to un-parent the starting scene view in order to make it disappear.</p>
Chet Haased82c8ac2013-08-26 14:20:16 -0700311 *
312 * @param sceneRoot The root of the transition hierarchy
313 * @param startValues The target values in the start scene
314 * @param startVisibility The target visibility in the start scene
315 * @param endValues The target values in the end scene
316 * @param endVisibility The target visibility in the end scene
317 * @return An Animator to be started at the appropriate time in the
318 * overall transition for this scene change. A null value means no animation
319 * should be run.
Chet Haasefaebd8f2012-05-18 14:17:57 -0700320 */
Chet Haased82c8ac2013-08-26 14:20:16 -0700321 public Animator onDisappear(ViewGroup sceneRoot,
Chet Haase6ebe3de2013-06-17 16:50:50 -0700322 TransitionValues startValues, int startVisibility,
323 TransitionValues endValues, int endVisibility) {
George Mount18ab7992014-06-25 17:04:51 -0700324 if ((mMode & OUT) != OUT) {
325 return null;
326 }
327
George Mountd6107a32014-03-10 16:51:16 -0700328 View startView = (startValues != null) ? startValues.view : null;
329 View endView = (endValues != null) ? endValues.view : null;
330 View overlayView = null;
331 View viewToKeep = null;
332 if (endView == null || endView.getParent() == null) {
333 if (endView != null) {
334 // endView was removed from its parent - add it to the overlay
335 overlayView = endView;
336 } else if (startView != null) {
337 // endView does not exist. Use startView only under certain
338 // conditions, because placing a view in an overlay necessitates
339 // it being removed from its current parent
340 if (startView.getParent() == null) {
341 // no parent - safe to use
342 overlayView = startView;
George Mountd4c3c912014-06-09 12:31:34 -0700343 } else if (startView.getParent() instanceof View) {
George Mountd6107a32014-03-10 16:51:16 -0700344 View startParent = (View) startView.getParent();
George Mountd4c3c912014-06-09 12:31:34 -0700345 if (!isValidTarget(startParent)) {
346 if (startView.isAttachedToWindow()) {
347 overlayView = copyViewImage(startView);
348 } else {
349 overlayView = startView;
350 }
351 } else if (startParent.getParent() == null) {
352 int id = startParent.getId();
353 if (id != View.NO_ID && sceneRoot.findViewById(id) != null
354 && mCanRemoveViews) {
355 // no parent, but its parent is unparented but the parent
356 // hierarchy has been replaced by a new hierarchy with the same id
357 // and it is safe to un-parent startView
358 overlayView = startView;
359 }
George Mountd6107a32014-03-10 16:51:16 -0700360 }
361 }
362 }
363 } else {
364 // visibility change
365 if (endVisibility == View.INVISIBLE) {
366 viewToKeep = endView;
367 } else {
368 // Becoming GONE
369 if (startView == endView) {
370 viewToKeep = endView;
371 } else {
372 overlayView = startView;
373 }
374 }
375 }
376 final int finalVisibility = endVisibility;
377 final ViewGroup finalSceneRoot = sceneRoot;
378
379 if (overlayView != null) {
380 // TODO: Need to do this for general case of adding to overlay
381 int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
382 int screenX = screenLoc[0];
383 int screenY = screenLoc[1];
384 int[] loc = new int[2];
385 sceneRoot.getLocationOnScreen(loc);
386 overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
387 overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
388 sceneRoot.getOverlay().add(overlayView);
389 Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
390 if (animator == null) {
391 sceneRoot.getOverlay().remove(overlayView);
392 } else {
393 final View finalOverlayView = overlayView;
394 animator.addListener(new AnimatorListenerAdapter() {
395 @Override
396 public void onAnimationEnd(Animator animation) {
397 finalSceneRoot.getOverlay().remove(finalOverlayView);
398 }
George Mountd6107a32014-03-10 16:51:16 -0700399 });
400 }
401 return animator;
402 }
403
404 if (viewToKeep != null) {
George Mount1b2fb2c2014-04-25 17:07:58 -0700405 int originalVisibility = viewToKeep.getVisibility();
George Mountd6107a32014-03-10 16:51:16 -0700406 viewToKeep.setVisibility(View.VISIBLE);
407 Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
408 if (animator == null) {
George Mount1b2fb2c2014-04-25 17:07:58 -0700409 viewToKeep.setVisibility(originalVisibility);
George Mountd6107a32014-03-10 16:51:16 -0700410 } else {
411 final View finalViewToKeep = viewToKeep;
412 animator.addListener(new AnimatorListenerAdapter() {
413 boolean mCanceled = false;
414
415 @Override
416 public void onAnimationPause(Animator animation) {
417 if (!mCanceled) {
418 finalViewToKeep.setVisibility(finalVisibility);
419 }
420 }
421
422 @Override
423 public void onAnimationResume(Animator animation) {
424 if (!mCanceled) {
425 finalViewToKeep.setVisibility(View.VISIBLE);
426 }
427 }
428
429 @Override
430 public void onAnimationCancel(Animator animation) {
431 mCanceled = true;
432 }
433
434 @Override
435 public void onAnimationEnd(Animator animation) {
436 if (!mCanceled) {
437 finalViewToKeep.setVisibility(finalVisibility);
438 }
439 }
440 });
441 }
442 return animator;
443 }
444 return null;
445 }
446
George Mountd4c3c912014-06-09 12:31:34 -0700447 private View copyViewImage(View view) {
448 int width = view.getWidth();
449 int height = view.getHeight();
450 if (width <= 0 || height <= 0) {
451 return null;
452 }
453 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
454 Canvas canvas = new Canvas(bitmap);
455 view.draw(canvas);
456 final BitmapDrawable drawable = new BitmapDrawable(bitmap);
457
458 View overlayView = new View(view.getContext());
459 overlayView.setBackground(drawable);
460 int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
461 int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
462 overlayView.measure(widthSpec, heightSpec);
463 overlayView.layout(0, 0, width, height);
464 return overlayView;
465 }
466
George Mount4c20ea22014-06-17 10:14:39 -0700467 @Override
468 boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
469 VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
470 if (oldValues == null && newValues == null) {
471 return false;
472 }
473 return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE ||
474 changeInfo.endVisibility == View.VISIBLE);
475 }
476
George Mountd6107a32014-03-10 16:51:16 -0700477 /**
478 * The default implementation of this method returns a null Animator. Subclasses should
479 * override this method to make targets disappear with the desired transition. The
480 * method should only be called from
481 * {@link #onDisappear(ViewGroup, TransitionValues, int, TransitionValues, int)}.
482 *
483 * @param sceneRoot The root of the transition hierarchy
484 * @param view The View to make disappear. This will be in the target scene's View
485 * hierarchy or in an {@link android.view.ViewGroupOverlay} and will be
486 * VISIBLE.
487 * @param startValues The target values in the start scene
488 * @param endValues The target values in the end scene
489 * @return An Animator to be started at the appropriate time in the
490 * overall transition for this scene change. A null value means no animation
491 * should be run.
492 */
493 public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
494 TransitionValues endValues) {
Chet Haase6ebe3de2013-06-17 16:50:50 -0700495 return null;
496 }
Chet Haasefaebd8f2012-05-18 14:17:57 -0700497}