1 /* 2 * Copyright 2023 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.compose.animation.scene.transformation 18 19 import androidx.compose.ui.geometry.Offset 20 import com.android.compose.animation.scene.Edge 21 import com.android.compose.animation.scene.Element 22 import com.android.compose.animation.scene.ElementMatcher 23 import com.android.compose.animation.scene.SceneKey 24 import com.android.compose.animation.scene.SceneTransitionLayoutImpl 25 import com.android.compose.animation.scene.TransitionState 26 27 /** Translate an element from an edge of the layout. */ 28 internal class EdgeTranslate( 29 override val matcher: ElementMatcher, 30 private val edge: Edge, 31 private val startsOutsideLayoutBounds: Boolean = true, 32 ) : PropertyTransformation<Offset> { transformnull33 override fun transform( 34 layoutImpl: SceneTransitionLayoutImpl, 35 scene: SceneKey, 36 element: Element, 37 sceneState: Element.SceneState, 38 transition: TransitionState.Transition, 39 value: Offset 40 ): Offset { 41 val sceneSize = layoutImpl.scene(scene).targetSize 42 val elementSize = sceneState.targetSize 43 if (elementSize == Element.SizeUnspecified) { 44 return value 45 } 46 47 return when (edge) { 48 Edge.Top -> 49 if (startsOutsideLayoutBounds) { 50 Offset(value.x, -elementSize.height.toFloat()) 51 } else { 52 Offset(value.x, 0f) 53 } 54 Edge.Left -> 55 if (startsOutsideLayoutBounds) { 56 Offset(-elementSize.width.toFloat(), value.y) 57 } else { 58 Offset(0f, value.y) 59 } 60 Edge.Bottom -> 61 if (startsOutsideLayoutBounds) { 62 Offset(value.x, sceneSize.height.toFloat()) 63 } else { 64 Offset(value.x, (sceneSize.height - elementSize.height).toFloat()) 65 } 66 Edge.Right -> 67 if (startsOutsideLayoutBounds) { 68 Offset(sceneSize.width.toFloat(), value.y) 69 } else { 70 Offset((sceneSize.width - elementSize.width).toFloat(), value.y) 71 } 72 } 73 } 74 } 75