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 17 package com.android.wallpaper.picker.preview.ui.transition 18 19 import android.animation.Animator 20 import android.animation.ObjectAnimator 21 import android.animation.PropertyValuesHolder 22 import android.view.ViewGroup 23 import androidx.core.animation.doOnStart 24 import androidx.transition.Transition 25 import androidx.transition.TransitionValues 26 27 class ChangeScaleAndPosition : Transition() { 28 captureStartValuesnull29 override fun captureStartValues(transitionValues: TransitionValues) { 30 captureValues(transitionValues) 31 } 32 captureEndValuesnull33 override fun captureEndValues(transitionValues: TransitionValues) { 34 captureValues(transitionValues) 35 } 36 getTransitionPropertiesnull37 override fun getTransitionProperties() = properties 38 39 private fun captureValues(transitionValues: TransitionValues) { 40 val view = transitionValues.view 41 val values = transitionValues.values 42 43 val screenLocation = IntArray(2) 44 view.getLocationOnScreen(screenLocation) 45 values[PROPNAME_POSX] = screenLocation[0] 46 values[PROPNAME_POSY] = screenLocation[1] 47 48 values[PROPNAME_WIDTH] = view.width 49 values[PROPNAME_HEIGHT] = view.height 50 } 51 createAnimatornull52 override fun createAnimator( 53 sceneRoot: ViewGroup, 54 startValues: TransitionValues?, 55 endValues: TransitionValues? 56 ): Animator? { 57 if (startValues == null || endValues == null) return null 58 59 val leftDelta = 60 ((startValues.values[PROPNAME_POSX] as Int) - (endValues.values[PROPNAME_POSX] as Int)) 61 .toFloat() 62 val topDelta = 63 ((startValues.values[PROPNAME_POSY] as Int) - (endValues.values[PROPNAME_POSY] as Int)) 64 .toFloat() 65 66 val scaleWidth = 67 (startValues.values[PROPNAME_WIDTH] as Int).toFloat() / 68 (endValues.values[PROPNAME_WIDTH] as Int).toFloat() 69 val scaleHeight = 70 (startValues.values[PROPNAME_HEIGHT] as Int).toFloat() / 71 (endValues.values[PROPNAME_HEIGHT] as Int).toFloat() 72 73 val view = endValues.view 74 val anim = 75 ObjectAnimator.ofPropertyValuesHolder( 76 view, 77 PropertyValuesHolder.ofFloat("scaleX", scaleWidth, 1f), 78 PropertyValuesHolder.ofFloat("scaleY", scaleHeight, 1f), 79 PropertyValuesHolder.ofFloat("translationX", leftDelta, 0f), 80 PropertyValuesHolder.ofFloat("translationY", topDelta, 0f) 81 ) 82 anim.doOnStart { 83 view.pivotX = 0f 84 view.pivotY = 0f 85 } 86 return anim 87 } 88 89 companion object { 90 private const val PROPNAME_POSX = "changeScaleAndPosition:posX" 91 private const val PROPNAME_POSY = "changeScaleAndPosition:posY" 92 private const val PROPNAME_WIDTH = "changeScaleAndPosition:width" 93 private const val PROPNAME_HEIGHT = "changeScaleAndPosition:height" 94 val properties = arrayOf(PROPNAME_POSX, PROPNAME_POSY, PROPNAME_WIDTH, PROPNAME_HEIGHT) 95 } 96 } 97