1 /* 2 * Copyright (C) 2015 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 package com.android.launcher3.touch; 17 18 import static com.android.launcher3.LauncherState.ALL_APPS; 19 import static com.android.launcher3.LauncherState.NORMAL; 20 import static com.android.launcher3.anim.Interpolators.EMPHASIZED; 21 import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE; 22 import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE; 23 import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; 24 import static com.android.launcher3.anim.Interpolators.INSTANT; 25 import static com.android.launcher3.anim.Interpolators.LINEAR; 26 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; 27 import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH; 28 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE; 29 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE; 30 import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE; 31 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; 32 import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; 33 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; 34 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE; 35 36 import android.view.MotionEvent; 37 import android.view.animation.Interpolator; 38 39 import com.android.launcher3.AbstractFloatingView; 40 import com.android.launcher3.Launcher; 41 import com.android.launcher3.LauncherState; 42 import com.android.launcher3.anim.Interpolators; 43 import com.android.launcher3.states.StateAnimationConfig; 44 45 /** 46 * TouchController to switch between NORMAL and ALL_APPS state. 47 */ 48 public class AllAppsSwipeController extends AbstractStateChangeTouchController { 49 50 private static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f; 51 private static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f; 52 private static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = 0.1f; 53 private static final float ALL_APPS_STAGGERED_FADE_THRESHOLD = 0.5f; 54 55 public static final Interpolator ALL_APPS_SCRIM_RESPONDER = 56 Interpolators.clampToProgress( 57 LINEAR, ALL_APPS_SCRIM_VISIBLE_THRESHOLD, ALL_APPS_STAGGERED_FADE_THRESHOLD); 58 public static final Interpolator ALL_APPS_CLAMPING_RESPONDER = 59 Interpolators.clampToProgress( 60 LINEAR, 61 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, 62 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD); 63 64 // ---- Custom interpolators for NORMAL -> ALL_APPS on phones only. ---- 65 66 public static final float ALL_APPS_STATE_TRANSITION_ATOMIC = 0.3333f; 67 public static final float ALL_APPS_STATE_TRANSITION_MANUAL = 0.4f; 68 private static final float ALL_APPS_FADE_END_ATOMIC = 0.8333f; 69 private static final float ALL_APPS_FADE_END_MANUAL = 0.8f; 70 private static final float ALL_APPS_FULL_DEPTH_PROGRESS = 0.5f; 71 private static final float SCRIM_FADE_START_ATOMIC = 0.2642f; 72 private static final float SCRIM_FADE_START_MANUAL = 0.117f; 73 private static final float WORKSPACE_MOTION_START_ATOMIC = 0.1667f; 74 75 private static final Interpolator LINEAR_EARLY_MANUAL = 76 Interpolators.clampToProgress(LINEAR, 0f, ALL_APPS_STATE_TRANSITION_MANUAL); 77 private static final Interpolator STEP_TRANSITION_ATOMIC = 78 Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION_ATOMIC); 79 private static final Interpolator STEP_TRANSITION_MANUAL = 80 Interpolators.clampToProgress(FINAL_FRAME, 0f, ALL_APPS_STATE_TRANSITION_MANUAL); 81 82 // The blur to All Apps is set to be complete when the interpolator is at 0.5. 83 private static final Interpolator BLUR_ADJUSTED = 84 Interpolators.mapToProgress(LINEAR, 0f, ALL_APPS_FULL_DEPTH_PROGRESS); 85 public static final Interpolator BLUR_ATOMIC = 86 Interpolators.clampToProgress( 87 BLUR_ADJUSTED, WORKSPACE_MOTION_START_ATOMIC, ALL_APPS_STATE_TRANSITION_ATOMIC); 88 public static final Interpolator BLUR_MANUAL = 89 Interpolators.clampToProgress(BLUR_ADJUSTED, 0f, ALL_APPS_STATE_TRANSITION_MANUAL); 90 91 public static final Interpolator WORKSPACE_FADE_ATOMIC = STEP_TRANSITION_ATOMIC; 92 public static final Interpolator WORKSPACE_FADE_MANUAL = STEP_TRANSITION_MANUAL; 93 94 public static final Interpolator WORKSPACE_SCALE_ATOMIC = 95 Interpolators.clampToProgress( 96 EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START_ATOMIC, 97 ALL_APPS_STATE_TRANSITION_ATOMIC); 98 public static final Interpolator WORKSPACE_SCALE_MANUAL = LINEAR_EARLY_MANUAL; 99 100 public static final Interpolator HOTSEAT_FADE_ATOMIC = STEP_TRANSITION_ATOMIC; 101 public static final Interpolator HOTSEAT_FADE_MANUAL = STEP_TRANSITION_MANUAL; 102 103 public static final Interpolator HOTSEAT_SCALE_ATOMIC = 104 Interpolators.clampToProgress( 105 EMPHASIZED_ACCELERATE, WORKSPACE_MOTION_START_ATOMIC, 106 ALL_APPS_STATE_TRANSITION_ATOMIC); 107 public static final Interpolator HOTSEAT_SCALE_MANUAL = LINEAR_EARLY_MANUAL; 108 109 public static final Interpolator HOTSEAT_TRANSLATE_ATOMIC = STEP_TRANSITION_ATOMIC; 110 public static final Interpolator HOTSEAT_TRANSLATE_MANUAL = STEP_TRANSITION_MANUAL; 111 112 public static final Interpolator SCRIM_FADE_ATOMIC = 113 Interpolators.clampToProgress( 114 Interpolators.mapToProgress(LINEAR, 0f, 0.8f), 115 SCRIM_FADE_START_ATOMIC, ALL_APPS_STATE_TRANSITION_ATOMIC); 116 public static final Interpolator SCRIM_FADE_MANUAL = 117 Interpolators.clampToProgress( 118 LINEAR, SCRIM_FADE_START_MANUAL, ALL_APPS_STATE_TRANSITION_MANUAL); 119 120 public static final Interpolator ALL_APPS_FADE_ATOMIC = 121 Interpolators.clampToProgress( 122 Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.2f, 1f), 123 ALL_APPS_STATE_TRANSITION_ATOMIC, ALL_APPS_FADE_END_ATOMIC); 124 public static final Interpolator ALL_APPS_FADE_MANUAL = 125 Interpolators.clampToProgress( 126 LINEAR, ALL_APPS_STATE_TRANSITION_MANUAL, ALL_APPS_FADE_END_MANUAL); 127 128 public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_ATOMIC = 129 Interpolators.clampToProgress( 130 Interpolators.mapToProgress(EMPHASIZED_DECELERATE, 0.4f, 1f), 131 ALL_APPS_STATE_TRANSITION_ATOMIC, 1f); 132 public static final Interpolator ALL_APPS_VERTICAL_PROGRESS_MANUAL = LINEAR; 133 134 // -------- 135 AllAppsSwipeController(Launcher l)136 public AllAppsSwipeController(Launcher l) { 137 super(l, SingleAxisSwipeDetector.VERTICAL); 138 } 139 140 @Override canInterceptTouch(MotionEvent ev)141 protected boolean canInterceptTouch(MotionEvent ev) { 142 if (mCurrentAnimation != null) { 143 // If we are already animating from a previous state, we can intercept. 144 return true; 145 } 146 if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { 147 return false; 148 } 149 if (!mLauncher.isInState(NORMAL) && !mLauncher.isInState(ALL_APPS)) { 150 // Don't listen for the swipe gesture if we are already in some other state. 151 return false; 152 } 153 if (mLauncher.isInState(ALL_APPS) && !mLauncher.getAppsView().shouldContainerScroll(ev)) { 154 return false; 155 } 156 return true; 157 } 158 159 @Override getTargetState(LauncherState fromState, boolean isDragTowardPositive)160 protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) { 161 if (fromState == NORMAL && isDragTowardPositive) { 162 return ALL_APPS; 163 } else if (fromState == ALL_APPS && !isDragTowardPositive) { 164 return NORMAL; 165 } 166 return fromState; 167 } 168 169 @Override initCurrentAnimation()170 protected float initCurrentAnimation() { 171 float range = getShiftRange(); 172 StateAnimationConfig config = getConfigForStates(mFromState, mToState); 173 config.duration = (long) (2 * range); 174 175 mCurrentAnimation = mLauncher.getStateManager() 176 .createAnimationToNewWorkspace(mToState, config); 177 float startVerticalShift = mFromState.getVerticalProgress(mLauncher) * range; 178 float endVerticalShift = mToState.getVerticalProgress(mLauncher) * range; 179 float totalShift = endVerticalShift - startVerticalShift; 180 return 1 / totalShift; 181 } 182 183 @Override getConfigForStates(LauncherState fromState, LauncherState toState)184 protected StateAnimationConfig getConfigForStates(LauncherState fromState, 185 LauncherState toState) { 186 StateAnimationConfig config = super.getConfigForStates(fromState, toState); 187 config.userControlled = true; 188 if (fromState == NORMAL && toState == ALL_APPS) { 189 applyNormalToAllAppsAnimConfig(mLauncher, config); 190 } else if (fromState == ALL_APPS && toState == NORMAL) { 191 applyAllAppsToNormalConfig(mLauncher, config); 192 } 193 return config; 194 } 195 196 /** 197 * Applies Animation config values for transition from all apps to home. 198 */ applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config)199 public static void applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config) { 200 if (launcher.getDeviceProfile().isTablet) { 201 config.setInterpolator(ANIM_SCRIM_FADE, 202 Interpolators.reverse(ALL_APPS_SCRIM_RESPONDER)); 203 config.setInterpolator(ANIM_ALL_APPS_FADE, FINAL_FRAME); 204 if (!config.userControlled) { 205 config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED); 206 } 207 config.setInterpolator(ANIM_WORKSPACE_SCALE, EMPHASIZED); 208 config.setInterpolator(ANIM_DEPTH, EMPHASIZED); 209 } else { 210 if (config.userControlled) { 211 config.setInterpolator(ANIM_DEPTH, Interpolators.reverse(BLUR_MANUAL)); 212 config.setInterpolator(ANIM_WORKSPACE_FADE, 213 Interpolators.reverse(WORKSPACE_FADE_MANUAL)); 214 config.setInterpolator(ANIM_WORKSPACE_SCALE, 215 Interpolators.reverse(WORKSPACE_SCALE_MANUAL)); 216 config.setInterpolator(ANIM_HOTSEAT_FADE, 217 Interpolators.reverse(HOTSEAT_FADE_MANUAL)); 218 config.setInterpolator(ANIM_HOTSEAT_SCALE, 219 Interpolators.reverse(HOTSEAT_SCALE_MANUAL)); 220 config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, 221 Interpolators.reverse(HOTSEAT_TRANSLATE_MANUAL)); 222 config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.reverse(SCRIM_FADE_MANUAL)); 223 config.setInterpolator(ANIM_ALL_APPS_FADE, 224 Interpolators.reverse(ALL_APPS_FADE_MANUAL)); 225 config.setInterpolator(ANIM_VERTICAL_PROGRESS, 226 Interpolators.reverse(ALL_APPS_VERTICAL_PROGRESS_MANUAL)); 227 } else { 228 config.setInterpolator(ANIM_SCRIM_FADE, 229 Interpolators.reverse(ALL_APPS_SCRIM_RESPONDER)); 230 config.setInterpolator(ANIM_ALL_APPS_FADE, ALL_APPS_CLAMPING_RESPONDER); 231 config.setInterpolator(ANIM_WORKSPACE_FADE, INSTANT); 232 config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE); 233 } 234 } 235 } 236 237 /** 238 * Applies Animation config values for transition from home to all apps. 239 */ applyNormalToAllAppsAnimConfig( Launcher launcher, StateAnimationConfig config)240 public static void applyNormalToAllAppsAnimConfig( 241 Launcher launcher, StateAnimationConfig config) { 242 if (launcher.getDeviceProfile().isTablet) { 243 config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT); 244 config.setInterpolator(ANIM_SCRIM_FADE, ALL_APPS_SCRIM_RESPONDER); 245 if (!config.userControlled) { 246 config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED); 247 } 248 config.setInterpolator(ANIM_WORKSPACE_SCALE, EMPHASIZED); 249 config.setInterpolator(ANIM_DEPTH, EMPHASIZED); 250 } else { 251 config.setInterpolator(ANIM_DEPTH, config.userControlled ? BLUR_MANUAL : BLUR_ATOMIC); 252 config.setInterpolator(ANIM_WORKSPACE_FADE, 253 config.userControlled ? WORKSPACE_FADE_MANUAL : WORKSPACE_FADE_ATOMIC); 254 config.setInterpolator(ANIM_WORKSPACE_SCALE, 255 config.userControlled ? WORKSPACE_SCALE_MANUAL : WORKSPACE_SCALE_ATOMIC); 256 config.setInterpolator(ANIM_HOTSEAT_FADE, 257 config.userControlled ? HOTSEAT_FADE_MANUAL : HOTSEAT_FADE_ATOMIC); 258 config.setInterpolator(ANIM_HOTSEAT_SCALE, 259 config.userControlled ? HOTSEAT_SCALE_MANUAL : HOTSEAT_SCALE_ATOMIC); 260 config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, 261 config.userControlled ? HOTSEAT_TRANSLATE_MANUAL : HOTSEAT_TRANSLATE_ATOMIC); 262 config.setInterpolator(ANIM_SCRIM_FADE, 263 config.userControlled ? SCRIM_FADE_MANUAL : SCRIM_FADE_ATOMIC); 264 config.setInterpolator(ANIM_ALL_APPS_FADE, 265 config.userControlled ? ALL_APPS_FADE_MANUAL : ALL_APPS_FADE_ATOMIC); 266 config.setInterpolator(ANIM_VERTICAL_PROGRESS, 267 config.userControlled 268 ? ALL_APPS_VERTICAL_PROGRESS_MANUAL 269 : ALL_APPS_VERTICAL_PROGRESS_ATOMIC); 270 } 271 } 272 } 273