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