1 /* 2 * Copyright (C) 2016 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 17 package com.android.systemui.statusbar; 18 19 import android.view.View; 20 21 import com.android.systemui.Interpolators; 22 import com.android.systemui.statusbar.stack.StackStateAnimator; 23 24 /** 25 * A helper to fade views in and out. 26 */ 27 public class CrossFadeHelper { 28 public static final long ANIMATION_DURATION_LENGTH = 210; 29 fadeOut(final View view, final Runnable endRunnable)30 public static void fadeOut(final View view, final Runnable endRunnable) { 31 fadeOut(view, ANIMATION_DURATION_LENGTH, 0, endRunnable); 32 } 33 fadeOut(final View view, long duration, int delay, final Runnable endRunnable)34 public static void fadeOut(final View view, long duration, int delay, 35 final Runnable endRunnable) { 36 view.animate().cancel(); 37 view.animate() 38 .alpha(0f) 39 .setDuration(duration) 40 .setInterpolator(Interpolators.ALPHA_OUT) 41 .setStartDelay(delay) 42 .withEndAction(new Runnable() { 43 @Override 44 public void run() { 45 if (endRunnable != null) { 46 endRunnable.run(); 47 } 48 view.setVisibility(View.INVISIBLE); 49 } 50 }); 51 if (view.hasOverlappingRendering()) { 52 view.animate().withLayer(); 53 } 54 } 55 fadeOut(View view, float fadeOutAmount)56 public static void fadeOut(View view, float fadeOutAmount) { 57 fadeOut(view, fadeOutAmount, true /* remap */); 58 } 59 60 /** 61 * Fade out a view by a given progress amount 62 * @param view the view to fade out 63 * @param fadeOutAmount how much the view is faded out. 0 means not at all and 1 means fully 64 * faded out 65 * @param remap whether the fade amount should be remapped to the shorter duration 66 * {@link #ANIMATION_DURATION_LENGTH} from the normal fade duration 67 * {@link StackStateAnimator#ANIMATION_DURATION_STANDARD} in order to have a faster fading. 68 * 69 * @see #fadeIn(View, float, boolean) 70 */ fadeOut(View view, float fadeOutAmount, boolean remap)71 public static void fadeOut(View view, float fadeOutAmount, boolean remap) { 72 view.animate().cancel(); 73 if (fadeOutAmount == 1.0f) { 74 view.setVisibility(View.INVISIBLE); 75 } else if (view.getVisibility() == View.INVISIBLE) { 76 view.setVisibility(View.VISIBLE); 77 } 78 if (remap) { 79 fadeOutAmount = mapToFadeDuration(fadeOutAmount); 80 } 81 float alpha = Interpolators.ALPHA_OUT.getInterpolation(1.0f - fadeOutAmount); 82 view.setAlpha(alpha); 83 updateLayerType(view, alpha); 84 } 85 mapToFadeDuration(float fadeOutAmount)86 private static float mapToFadeDuration(float fadeOutAmount) { 87 // Assuming a linear interpolator, we can easily map it to our new duration 88 float endPoint = (float) ANIMATION_DURATION_LENGTH 89 / (float) StackStateAnimator.ANIMATION_DURATION_STANDARD; 90 return Math.min(fadeOutAmount / endPoint, 1.0f); 91 } 92 updateLayerType(View view, float alpha)93 private static void updateLayerType(View view, float alpha) { 94 if (view.hasOverlappingRendering() && alpha > 0.0f && alpha < 1.0f) { 95 view.setLayerType(View.LAYER_TYPE_HARDWARE, null); 96 } else if (view.getLayerType() == View.LAYER_TYPE_HARDWARE) { 97 view.setLayerType(View.LAYER_TYPE_NONE, null); 98 } 99 } 100 fadeIn(final View view)101 public static void fadeIn(final View view) { 102 fadeIn(view, ANIMATION_DURATION_LENGTH, 0); 103 } 104 fadeIn(final View view, long duration, int delay)105 public static void fadeIn(final View view, long duration, int delay) { 106 view.animate().cancel(); 107 if (view.getVisibility() == View.INVISIBLE) { 108 view.setAlpha(0.0f); 109 view.setVisibility(View.VISIBLE); 110 } 111 view.animate() 112 .alpha(1f) 113 .setDuration(duration) 114 .setStartDelay(delay) 115 .setInterpolator(Interpolators.ALPHA_IN) 116 .withEndAction(null); 117 if (view.hasOverlappingRendering()) { 118 view.animate().withLayer(); 119 } 120 } 121 fadeIn(View view, float fadeInAmount)122 public static void fadeIn(View view, float fadeInAmount) { 123 fadeIn(view, fadeInAmount, true /* remap */); 124 } 125 126 /** 127 * Fade in a view by a given progress amount 128 * @param view the view to fade in 129 * @param fadeInAmount how much the view is faded in. 0 means not at all and 1 means fully 130 * faded in. 131 * @param remap whether the fade amount should be remapped to the shorter duration 132 * {@link #ANIMATION_DURATION_LENGTH} from the normal fade duration 133 * {@link StackStateAnimator#ANIMATION_DURATION_STANDARD} in order to have a faster fading. 134 * 135 * @see #fadeOut(View, float, boolean) 136 */ fadeIn(View view, float fadeInAmount, boolean remap)137 public static void fadeIn(View view, float fadeInAmount, boolean remap) { 138 view.animate().cancel(); 139 if (view.getVisibility() == View.INVISIBLE) { 140 view.setVisibility(View.VISIBLE); 141 } 142 if (remap) { 143 fadeInAmount = mapToFadeDuration(fadeInAmount); 144 } 145 float alpha = Interpolators.ALPHA_IN.getInterpolation(fadeInAmount); 146 view.setAlpha(alpha); 147 updateLayerType(view, alpha); 148 } 149 } 150