1 package com.android.wm.shell.windowdecor 2 3 import android.animation.ValueAnimator 4 import android.app.ActivityManager.RunningTaskInfo 5 import android.graphics.PointF 6 import android.graphics.Rect 7 import android.view.MotionEvent 8 import android.view.SurfaceControl 9 10 /** 11 * Creates an animator to shrink and position task after a user drags a fullscreen task from 12 * the top of the screen to transition it into freeform and before the user releases the task. The 13 * MoveToDesktopAnimator object also holds information about the state of the task that are 14 * accessed by the EnterDesktopTaskTransitionHandler. 15 */ 16 class MoveToDesktopAnimator @JvmOverloads constructor( 17 private val startBounds: Rect, 18 private val taskInfo: RunningTaskInfo, 19 private val taskSurface: SurfaceControl, 20 private val transactionFactory: () -> SurfaceControl.Transaction = 21 SurfaceControl::Transaction 22 ) { 23 companion object { 24 // The size of the screen during drag relative to the fullscreen size 25 const val DRAG_FREEFORM_SCALE: Float = 0.4f 26 const val ANIMATION_DURATION = 336 27 } 28 29 private val animatedTaskWidth 30 get() = dragToDesktopAnimator.animatedValue as Float * startBounds.width() 31 private val dragToDesktopAnimator: ValueAnimator = ValueAnimator.ofFloat(1f, 32 DRAG_FREEFORM_SCALE) 33 .setDuration(ANIMATION_DURATION.toLong()) 34 .apply { 35 val t = SurfaceControl.Transaction() 36 addUpdateListener { animation -> 37 val animatorValue = animation.animatedValue as Float 38 t.setScale(taskSurface, animatorValue, animatorValue) 39 .apply() 40 } 41 } 42 43 val taskId get() = taskInfo.taskId 44 val position: PointF = PointF(0.0f, 0.0f) 45 46 /** 47 * Starts the animation that scales the task down. 48 */ 49 fun startAnimation() { 50 dragToDesktopAnimator.start() 51 } 52 53 /** 54 * Uses the position of the motion event and the current scale of the task as defined by the 55 * ValueAnimator to update the local position variable and set the task surface's position 56 */ 57 fun updatePosition(ev: MotionEvent) { 58 position.x = ev.x - animatedTaskWidth / 2 59 position.y = ev.y 60 61 val t = transactionFactory() 62 t.setPosition(taskSurface, position.x, position.y) 63 t.apply() 64 } 65 66 /** 67 * Ends the animation, setting the scale and position to the final animation value 68 */ 69 fun endAnimator() { 70 dragToDesktopAnimator.end() 71 } 72 }