1/* 2 * Copyright (C) 2018 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 */ 16package com.android.quickstep.views; 17 18import static com.android.launcher3.LauncherAppTransitionManagerImpl.ALL_APPS_PROGRESS_OFF_SCREEN; 19import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA; 20import static com.android.launcher3.LauncherState.NORMAL; 21import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; 22 23import android.animation.AnimatorSet; 24import android.animation.ObjectAnimator; 25import android.annotation.TargetApi; 26import android.content.Context; 27import android.graphics.Canvas; 28import android.graphics.Rect; 29import android.os.Build; 30import android.util.AttributeSet; 31import android.util.FloatProperty; 32import android.view.View; 33import android.view.ViewDebug; 34 35import com.android.launcher3.DeviceProfile; 36import com.android.launcher3.Launcher; 37import com.android.launcher3.LauncherState; 38import com.android.launcher3.R; 39import com.android.launcher3.anim.Interpolators; 40import com.android.launcher3.views.ScrimView; 41import com.android.quickstep.OverviewInteractionState; 42import com.android.quickstep.util.ClipAnimationHelper; 43import com.android.quickstep.util.LayoutUtils; 44 45/** 46 * {@link RecentsView} used in Launcher activity 47 */ 48@TargetApi(Build.VERSION_CODES.O) 49public class LauncherRecentsView extends RecentsView<Launcher> { 50 51 public static final FloatProperty<LauncherRecentsView> TRANSLATION_Y_FACTOR = 52 new FloatProperty<LauncherRecentsView>("translationYFactor") { 53 54 @Override 55 public void setValue(LauncherRecentsView view, float v) { 56 view.setTranslationYFactor(v); 57 } 58 59 @Override 60 public Float get(LauncherRecentsView view) { 61 return view.mTranslationYFactor; 62 } 63 }; 64 65 @ViewDebug.ExportedProperty(category = "launcher") 66 private float mTranslationYFactor; 67 68 public LauncherRecentsView(Context context) { 69 this(context, null); 70 } 71 72 public LauncherRecentsView(Context context, AttributeSet attrs) { 73 this(context, attrs, 0); 74 } 75 76 public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { 77 super(context, attrs, defStyleAttr); 78 setContentAlpha(0); 79 } 80 81 @Override 82 protected void onAllTasksRemoved() { 83 mActivity.getStateManager().goToState(NORMAL); 84 } 85 86 @Override 87 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 88 super.onLayout(changed, left, top, right, bottom); 89 setTranslationYFactor(mTranslationYFactor); 90 } 91 92 public void setTranslationYFactor(float translationFactor) { 93 mTranslationYFactor = translationFactor; 94 setTranslationY(computeTranslationYForFactor(mTranslationYFactor)); 95 } 96 97 public float computeTranslationYForFactor(float translationYFactor) { 98 return translationYFactor * (getPaddingBottom() - getPaddingTop()); 99 } 100 101 @Override 102 public void draw(Canvas canvas) { 103 maybeDrawEmptyMessage(canvas); 104 super.draw(canvas); 105 } 106 107 @Override 108 public void onViewAdded(View child) { 109 super.onViewAdded(child); 110 updateEmptyMessage(); 111 } 112 113 @Override 114 protected void onTaskStackUpdated() { 115 // Lazily update the empty message only when the task stack is reapplied 116 updateEmptyMessage(); 117 } 118 119 /** 120 * Animates adjacent tasks and translate hotseat off screen as well. 121 */ 122 @Override 123 public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv, 124 ClipAnimationHelper helper) { 125 AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv, helper); 126 127 if (!OverviewInteractionState.getInstance(mActivity).isSwipeUpGestureEnabled()) { 128 // Hotseat doesn't move when opening recents with the button, 129 // so don't animate it here either. 130 return anim; 131 } 132 133 float allAppsProgressOffscreen = ALL_APPS_PROGRESS_OFF_SCREEN; 134 LauncherState state = mActivity.getStateManager().getState(); 135 if ((state.getVisibleElements(mActivity) & ALL_APPS_HEADER_EXTRA) != 0) { 136 float maxShiftRange = mActivity.getDeviceProfile().heightPx; 137 float currShiftRange = mActivity.getAllAppsController().getShiftRange(); 138 allAppsProgressOffscreen = 1f + (maxShiftRange - currShiftRange) / maxShiftRange; 139 } 140 anim.play(ObjectAnimator.ofFloat( 141 mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen)); 142 143 ObjectAnimator dragHandleAnim = ObjectAnimator.ofInt( 144 mActivity.findViewById(R.id.scrim_view), ScrimView.DRAG_HANDLE_ALPHA, 0); 145 dragHandleAnim.setInterpolator(Interpolators.ACCEL_2); 146 anim.play(dragHandleAnim); 147 148 return anim; 149 } 150 151 @Override 152 protected void getTaskSize(DeviceProfile dp, Rect outRect) { 153 LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect); 154 } 155 156 @Override 157 protected void onTaskLaunched(boolean success) { 158 if (success) { 159 mActivity.getStateManager().goToState(NORMAL, false /* animate */); 160 } else { 161 LauncherState state = mActivity.getStateManager().getState(); 162 mActivity.getAllAppsController().setState(state); 163 } 164 super.onTaskLaunched(success); 165 } 166 167 @Override 168 public boolean shouldUseMultiWindowTaskSizeStrategy() { 169 return mActivity.isInMultiWindowModeCompat(); 170 } 171} 172