1ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann/* 2ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * Copyright (C) 2012 The Android Open Source Project 3ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * 4ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License"); 5ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * you may not use this file except in compliance with the License. 6ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * You may obtain a copy of the License at 7ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * 8ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * http://www.apache.org/licenses/LICENSE-2.0 9ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * 10ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * Unless required by applicable law or agreed to in writing, software 11ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS, 12ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * See the License for the specific language governing permissions and 14ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * limitations under the License. 15ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann */ 16ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 17ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannpackage com.android.contacts.editor; 18ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 19ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.animation.Animator; 20ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.animation.Animator.AnimatorListener; 21ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.animation.AnimatorListenerAdapter; 22ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.animation.AnimatorSet; 23ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.animation.ObjectAnimator; 24ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.view.View; 25ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.view.ViewGroup; 26ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.view.ViewParent; 27ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport android.widget.LinearLayout; 28ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 29e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.SchedulingUtils; 30e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.google.common.collect.Lists; 31e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng 32ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannimport java.util.List; 33ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 34ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann/** 35ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * Configures animations for typical use-cases 36ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann */ 37ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmannpublic class EditorAnimator { 38ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private static EditorAnimator sInstance = new EditorAnimator(); 39ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 40ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public static EditorAnimator getInstance() { 41ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann return sInstance; 42ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 43ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 44ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann /** Private constructor for singleton */ 45ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private EditorAnimator() { } 46ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 47ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private AnimatorRunner mRunner = new AnimatorRunner(); 48ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 49ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void removeEditorView(final View victim) { 50ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.endOldAnimation(); 51ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final int offset = victim.getHeight(); 52ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 53ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<View> viewsToMove = getViewsBelowOf(victim); 54ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<Animator> animators = Lists.newArrayList(); 55ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 56ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Fade out 57ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ObjectAnimator fadeOutAnimator = 58ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann ObjectAnimator.ofFloat(victim, View.ALPHA, 1.0f, 0.0f); 59ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeOutAnimator.setDuration(200); 60ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann animators.add(fadeOutAnimator); 61ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 62ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Translations 63ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann translateViews(animators, viewsToMove, 0.0f, -offset, 100, 200); 64ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 65ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.run(animators, new AnimatorListenerAdapter() { 66ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann @Override 67ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void onAnimationEnd(Animator animation) { 68ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Clean up: Remove all the translations 69ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann for (int i = 0; i < viewsToMove.size(); i++) { 70ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final View view = viewsToMove.get(i); 71ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann view.setTranslationY(0.0f); 72ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 73ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Remove our target view (if parent is null, we were run several times by quick 74ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // fingers. Just ignore) 75ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ViewGroup victimParent = (ViewGroup) victim.getParent(); 76ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann if (victimParent != null) { 77ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann victimParent.removeView(victim); 78ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 79ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 80ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann }); 81ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 82ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 83ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee /** 84ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee * Slides the view into its new height, while simultaneously fading it into view. 85ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee * 86ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee * @param target The target view to perform the animation on. 87ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee * @param previousHeight The previous height of the view before its height was changed. 88ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee * Needed because the view does not store any state information about its previous height. 89ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee */ 90ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee public void slideAndFadeIn(final ViewGroup target, final int previousHeight) { 91ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee mRunner.endOldAnimation(); 92ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee target.setVisibility(View.VISIBLE); 93ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee target.setAlpha(0.0f); 94ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee target.requestFocus(); 95ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee SchedulingUtils.doAfterLayout(target, new Runnable() { 96ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee @Override 97ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee public void run() { 98ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee final int offset = target.getHeight() - previousHeight; 99ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee final List<Animator> animators = Lists.newArrayList(); 100ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 101ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee // Translations 102ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee final List<View> viewsToMove = getViewsBelowOf(target); 103ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 104ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee translateViews(animators, viewsToMove, -offset, 0.0f, 0, 200); 105ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 106ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee // Fade in 107ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat( 108ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee target, View.ALPHA, 0.0f, 1.0f); 109ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee fadeInAnimator.setDuration(200); 110ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee fadeInAnimator.setStartDelay(200); 111ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee animators.add(fadeInAnimator); 112ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 113ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee mRunner.run(animators); 114ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee } 115ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee }); 116ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee } 117ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee 118ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void expandOrganization(final View addOrganizationButton, 119ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ViewGroup organizationSectionViewContainer) { 120ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.endOldAnimation(); 121ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Make the new controls visible and do one layout pass (so that we can measure) 122ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann organizationSectionViewContainer.setVisibility(View.VISIBLE); 123ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann organizationSectionViewContainer.setAlpha(0.0f); 124ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann organizationSectionViewContainer.requestFocus(); 1256f5557e3dc3cd12182026bdfea17b15d4d9b7dfcJosh Gargus SchedulingUtils.doAfterLayout(addOrganizationButton, new Runnable() { 126ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann @Override 127ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void run() { 128ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // How many pixels extra do we need? 129ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final int offset = organizationSectionViewContainer.getHeight() - 130ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann addOrganizationButton.getHeight(); 131ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<Animator> animators = Lists.newArrayList(); 132ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 133ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Fade out 134ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ObjectAnimator fadeOutAnimator = ObjectAnimator.ofFloat( 135ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann addOrganizationButton, View.ALPHA, 1.0f, 0.0f); 136ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeOutAnimator.setDuration(200); 137ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann animators.add(fadeOutAnimator); 138ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 139ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Translations 140ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<View> viewsToMove = getViewsBelowOf(organizationSectionViewContainer); 141ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann translateViews(animators, viewsToMove, -offset, 0.0f, 0, 200); 142ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Fade in 143ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat( 144ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann organizationSectionViewContainer, View.ALPHA, 0.0f, 1.0f); 145ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeInAnimator.setDuration(200); 146ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeInAnimator.setStartDelay(200); 147ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann animators.add(fadeInAnimator); 148ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 149ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.run(animators); 150ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 151ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann }); 152ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 153ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 154ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void showAddFieldFooter(final View view) { 155ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.endOldAnimation(); 156ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann if (view.getVisibility() == View.VISIBLE) return; 157ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Make the new controls visible and do one layout pass (so that we can measure) 158ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann view.setVisibility(View.VISIBLE); 159ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann view.setAlpha(0.0f); 1606f5557e3dc3cd12182026bdfea17b15d4d9b7dfcJosh Gargus SchedulingUtils.doAfterLayout(view, new Runnable() { 161ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann @Override 162ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void run() { 163ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // How many pixels extra do we need? 164ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final int offset = view.getHeight(); 165ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 166ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<Animator> animators = Lists.newArrayList(); 167ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 168ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Translations 169ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<View> viewsToMove = getViewsBelowOf(view); 170ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann translateViews(animators, viewsToMove, -offset, 0.0f, 0, 200); 171ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 172ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Fade in 173ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat( 174ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann view, View.ALPHA, 0.0f, 1.0f); 175ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeInAnimator.setDuration(200); 176ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeInAnimator.setStartDelay(200); 177ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann animators.add(fadeInAnimator); 178ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 179ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.run(animators); 180ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 181ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann }); 182ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 183ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 184ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void hideAddFieldFooter(final View victim) { 185ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.endOldAnimation(); 186ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann if (victim.getVisibility() == View.GONE) return; 187ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final int offset = victim.getHeight(); 188ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 189ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<View> viewsToMove = getViewsBelowOf(victim); 190ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<Animator> animators = Lists.newArrayList(); 191ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 192ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Fade out 193ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ObjectAnimator fadeOutAnimator = 194ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann ObjectAnimator.ofFloat(victim, View.ALPHA, 1.0f, 0.0f); 195ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann fadeOutAnimator.setDuration(200); 196ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann animators.add(fadeOutAnimator); 197ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 198ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Translations 199ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann translateViews(animators, viewsToMove, 0.0f, -offset, 100, 200); 200ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 201ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Combine 202ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mRunner.run(animators, new AnimatorListenerAdapter() { 203ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann @Override 204ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void onAnimationEnd(Animator animation) { 205ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Clean up: Remove all the translations 206ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann for (int i = 0; i < viewsToMove.size(); i++) { 207ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final View view = viewsToMove.get(i); 208ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann view.setTranslationY(0.0f); 209ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 210ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 211ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann // Restore alpha (for next time), but hide the view for good now 212ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann victim.setAlpha(1.0f); 213ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann victim.setVisibility(View.GONE); 214ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 215ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann }); 216ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 217ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 218ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann /** 219ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * Creates a translation-animation for the given views 220ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann */ 221ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private static void translateViews(List<Animator> animators, List<View> views, float fromY, 222ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann float toY, int startDelay, int duration) { 223ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann for (int i = 0; i < views.size(); i++) { 224ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final View child = views.get(i); 225ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ObjectAnimator translateAnimator = 226ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, fromY, toY); 227ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann translateAnimator.setStartDelay(startDelay); 228ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann translateAnimator.setDuration(duration); 229ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann animators.add(translateAnimator); 230ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 231ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 232ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 233ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann /** 234ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee * Traverses up the view hierarchy and returns all views physically below this item. 2352e9ee9f15a1d928619a49ad259cdccbc8c7414dcChiao Cheng * 2362e9ee9f15a1d928619a49ad259cdccbc8c7414dcChiao Cheng * @return List of views that are below the given view. Empty list if parent of view is null. 237ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann */ 238ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private static List<View> getViewsBelowOf(View view) { 239ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ViewGroup victimParent = (ViewGroup) view.getParent(); 240ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final List<View> result = Lists.newArrayList(); 2412e9ee9f15a1d928619a49ad259cdccbc8c7414dcChiao Cheng if (victimParent != null) { 2422e9ee9f15a1d928619a49ad259cdccbc8c7414dcChiao Cheng final int index = victimParent.indexOfChild(view); 243ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee getViewsBelowOfRecursive(result, victimParent, index + 1, view); 2442e9ee9f15a1d928619a49ad259cdccbc8c7414dcChiao Cheng } 245ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann return result; 246ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 247ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 248ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private static void getViewsBelowOfRecursive(List<View> result, ViewGroup container, 249ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee int index, View target) { 250ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann for (int i = index; i < container.getChildCount(); i++) { 251ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee View view = container.getChildAt(i); 252ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee // consider the child view below the target view only if it is physically 253ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee // below the view on-screen, using half the height of the target view as the 254ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee // baseline 255ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee if (view.getY() > (target.getY() + target.getHeight() / 2)) { 256ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee result.add(view); 257ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee } 258ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 259ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 260ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final ViewParent parent = container.getParent(); 261ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann if (parent instanceof LinearLayout) { 262ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final LinearLayout parentLayout = (LinearLayout) parent; 263ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee int containerIndex = parentLayout.indexOfChild(container); 264ba48d21f2ab25c8ffb30198a752e5cd215553728Yorke Lee getViewsBelowOfRecursive(result, parentLayout, containerIndex + 1, target); 265ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 266ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 267ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 268ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann /** 269ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * Keeps a reference to the last animator, so that we can end that early if the user 270ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann * quickly pushes buttons. Removes the reference once the animation has finished 271ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann */ 272ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann /* package */ static class AnimatorRunner extends AnimatorListenerAdapter { 273ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann private Animator mLastAnimator; 274ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 275ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann @Override 276ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void onAnimationEnd(Animator animation) { 277ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mLastAnimator = null; 278ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 279ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 280ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void run(List<Animator> animators) { 281ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann run(animators, null); 282ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 283ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 284ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void run(List<Animator> animators, AnimatorListener listener) { 285ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann final AnimatorSet set = new AnimatorSet(); 286ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann set.playTogether(animators); 287ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann if (listener != null) set.addListener(listener); 288ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann set.addListener(this); 289ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mLastAnimator = set; 290ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann set.start(); 291ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 292ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann 293ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann public void endOldAnimation() { 294ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann if (mLastAnimator != null) { 295ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann mLastAnimator.end(); 296ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 297ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 298ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann } 299ca87e9c598929b5b6a62da9b80d2114168e24274Daniel Lehmann} 300