1 /* 2 * Copyright (C) 2019 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.quickstep.views; 18 19 import android.content.Context; 20 import android.graphics.drawable.Drawable; 21 import android.graphics.drawable.LayerDrawable; 22 23 import androidx.annotation.NonNull; 24 25 import com.android.launcher3.R; 26 27 /** 28 * A layer drawable for task content that transitions between two drawables by crossfading. Similar 29 * to {@link android.graphics.drawable.TransitionDrawable} but allows callers to control transition 30 * progress and provides a default, empty drawable. 31 */ 32 public final class TaskLayerDrawable extends LayerDrawable { 33 private final Drawable mEmptyDrawable; 34 private float mProgress; 35 TaskLayerDrawable(Context context)36 public TaskLayerDrawable(Context context) { 37 super(new Drawable[0]); 38 39 // Use empty drawable for both layers initially. 40 mEmptyDrawable = context.getResources().getDrawable( 41 R.drawable.empty_content_box, context.getTheme()); 42 addLayer(mEmptyDrawable); 43 addLayer(mEmptyDrawable); 44 setTransitionProgress(1.0f); 45 } 46 47 /** 48 * Immediately set the front-most drawable layer. 49 * 50 * @param drawable drawable to set 51 */ setCurrentDrawable(@onNull Drawable drawable)52 public void setCurrentDrawable(@NonNull Drawable drawable) { 53 setDrawable(0, drawable); 54 applyTransitionProgress(mProgress); 55 } 56 57 /** 58 * Immediately reset the drawable to showing the empty drawable. 59 */ resetDrawable()60 public void resetDrawable() { 61 setCurrentDrawable(mEmptyDrawable); 62 } 63 64 /** 65 * Prepare to start animating the transition by pushing the current drawable to the back and 66 * setting a new drawable to the front layer and making it invisible. 67 * 68 * @param endDrawable drawable to animate to 69 */ startNewTransition(@onNull Drawable endDrawable)70 public void startNewTransition(@NonNull Drawable endDrawable) { 71 Drawable oldDrawable = getDrawable(0); 72 setDrawable(1, oldDrawable); 73 setDrawable(0, endDrawable); 74 setTransitionProgress(0.0f); 75 } 76 77 /** 78 * Set the progress of the transition animation to crossfade the two drawables. 79 * 80 * @param progress current transition progress between 0 (front view invisible) and 1 81 * (front view visible) 82 */ setTransitionProgress(float progress)83 public void setTransitionProgress(float progress) { 84 if (progress > 1 || progress < 0) { 85 throw new IllegalArgumentException("Transition progress should be between 0 and 1"); 86 } 87 mProgress = progress; 88 applyTransitionProgress(progress); 89 } 90 applyTransitionProgress(float progress)91 private void applyTransitionProgress(float progress) { 92 int drawableAlpha = (int) (progress * 255); 93 getDrawable(0).setAlpha(drawableAlpha); 94 if (getDrawable(0) != getDrawable(1)) { 95 // Only do this if it's a different drawable so that it fades out. 96 // Otherwise, we'd just be overwriting the front drawable's alpha. 97 getDrawable(1).setAlpha(255 - drawableAlpha); 98 } 99 invalidateSelf(); 100 } 101 } 102