1 /* 2 * Copyright (C) 2024 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.wm.shell.back 17 18 import android.content.Context 19 import android.view.SurfaceControl 20 import android.window.BackEvent 21 import com.android.wm.shell.R 22 import com.android.wm.shell.RootTaskDisplayAreaOrganizer 23 import com.android.wm.shell.animation.Interpolators 24 import javax.inject.Inject 25 import kotlin.math.max 26 27 /** Class that defines cross-activity animation. */ 28 class DefaultCrossActivityBackAnimation 29 @Inject 30 constructor( 31 context: Context, 32 background: BackAnimationBackground, 33 rootTaskDisplayAreaOrganizer: RootTaskDisplayAreaOrganizer 34 ) : 35 CrossActivityBackAnimation( 36 context, 37 background, 38 rootTaskDisplayAreaOrganizer, 39 SurfaceControl.Transaction() 40 ) { 41 42 private val postCommitInterpolator = Interpolators.EMPHASIZED 43 private val enteringStartOffset = 44 context.resources.getDimension(R.dimen.cross_activity_back_entering_start_offset) 45 override val allowEnteringYShift = true 46 preparePreCommitClosingRectMovementnull47 override fun preparePreCommitClosingRectMovement(swipeEdge: Int) { 48 startClosingRect.set(backAnimRect) 49 50 // scale closing target into the middle for rhs and to the right for lhs 51 targetClosingRect.set(startClosingRect) 52 targetClosingRect.scaleCentered(MAX_SCALE) 53 if (swipeEdge != BackEvent.EDGE_RIGHT) { 54 targetClosingRect.offset( 55 startClosingRect.right - targetClosingRect.right - displayBoundsMargin, 56 0f 57 ) 58 } 59 } 60 preparePreCommitEnteringRectMovementnull61 override fun preparePreCommitEnteringRectMovement() { 62 // the entering target starts 96dp to the left of the screen edge... 63 startEnteringRect.set(startClosingRect) 64 startEnteringRect.offset(-enteringStartOffset, 0f) 65 // ...and gets scaled in sync with the closing target 66 targetEnteringRect.set(startEnteringRect) 67 targetEnteringRect.scaleCentered(MAX_SCALE) 68 } 69 getPostCommitAnimationDurationnull70 override fun getPostCommitAnimationDuration() = POST_COMMIT_DURATION 71 72 override fun onGestureCommitted(velocity: Float) { 73 // We enter phase 2 of the animation, the starting coordinates for phase 2 are the current 74 // coordinate of the gesture driven phase. Let's update the start and target rects and kick 75 // off the animator in the superclass 76 startClosingRect.set(currentClosingRect) 77 startEnteringRect.set(currentEnteringRect) 78 targetEnteringRect.set(backAnimRect) 79 targetClosingRect.set(backAnimRect) 80 targetClosingRect.offset(currentClosingRect.left + enteringStartOffset, 0f) 81 super.onGestureCommitted(velocity) 82 } 83 onPostCommitProgressnull84 override fun onPostCommitProgress(linearProgress: Float) { 85 super.onPostCommitProgress(linearProgress) 86 val closingAlpha = max(1f - linearProgress * 5, 0f) 87 val progress = postCommitInterpolator.getInterpolation(linearProgress) 88 currentClosingRect.setInterpolatedRectF(startClosingRect, targetClosingRect, progress) 89 applyTransform( 90 closingTarget?.leash, 91 currentClosingRect, 92 closingAlpha, 93 flingMode = FlingMode.FLING_BOUNCE 94 ) 95 currentEnteringRect.setInterpolatedRectF(startEnteringRect, targetEnteringRect, progress) 96 applyTransform( 97 enteringTarget?.leash, 98 currentEnteringRect, 99 1f, 100 flingMode = FlingMode.FLING_BOUNCE 101 ) 102 applyTransaction() 103 } 104 105 106 companion object { 107 private const val POST_COMMIT_DURATION = 450L 108 } 109 } 110