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.compose.animation.scene 18 19 import com.android.compose.animation.scene.content.state.TransitionState 20 21 /** 22 * A handler to specify how a transition should be interrupted. 23 * 24 * @see DefaultInterruptionHandler 25 * @see SceneTransitionsBuilder.interruptionHandler 26 */ 27 interface InterruptionHandler { 28 /** 29 * This function is called when [interrupted] is interrupted: it is currently animating between 30 * [interrupted.fromScene] and [interrupted.toScene], and we will now animate to 31 * [newTargetScene]. 32 * 33 * If this returns `null`, then the [default behavior][DefaultInterruptionHandler] will be used: 34 * we will animate from [interrupted.currentScene] and chaining will be enabled (see 35 * [InterruptionResult] for more information about chaining). 36 * 37 * @see InterruptionResult 38 */ onInterruptionnull39 fun onInterruption( 40 interrupted: TransitionState.Transition.ChangeScene, 41 newTargetScene: SceneKey, 42 ): InterruptionResult? 43 } 44 45 /** 46 * The result of an interruption that specifies how we should handle a transition A => B now that we 47 * have to animate to C. 48 * 49 * For instance, if the interrupted transition was A => B and currentScene = B: 50 * - animateFrom = B && chain = true => there will be 2 transitions running in parallel, A => B and 51 * B => C. 52 * - animateFrom = A && chain = true => there will be 2 transitions running in parallel, B => A and 53 * A => C. 54 * - animateFrom = B && chain = false => there will be 1 transition running, B => C. 55 * - animateFrom = A && chain = false => there will be 1 transition running, A => C. 56 */ 57 class InterruptionResult( 58 /** 59 * The scene we should animate from when transitioning to C. 60 * 61 * Important: This **must** be either [TransitionState.Transition.fromScene] or 62 * [TransitionState.Transition.toScene] of the transition that was interrupted. 63 */ 64 val animateFrom: SceneKey, 65 66 /** 67 * Whether chaining is enabled, i.e. if the new transition to C should run in parallel with the 68 * previous one(s) or if it should be the only remaining transition that is running. 69 */ 70 val chain: Boolean = true, 71 ) 72 73 /** 74 * The default interruption handler: we animate from [TransitionState.Transition.currentScene] and 75 * chaining is enabled. 76 */ 77 object DefaultInterruptionHandler : InterruptionHandler { 78 override fun onInterruption( 79 interrupted: TransitionState.Transition.ChangeScene, 80 newTargetScene: SceneKey, 81 ): InterruptionResult { 82 return InterruptionResult(animateFrom = interrupted.currentScene, chain = true) 83 } 84 } 85