# Back stack Implements a simple linear history: - The last element at the end of the stack is considered "active". - All other elements are considered stashed. - Children associated with stashed elements are off the screen but kept alive (see how the counter values reflect this on the video) The back stack can never be empty – it always contains at least one element. The back stack also supports different back press and operation strategies (see further down below). ## States ```kotlin enum class State { CREATED, ACTIVE, STASHED, DESTROYED, } ``` ## Visualisation of states Check out the apps in our [Coding challenges](../how-to-use-appyx/coding-challenges.md) – they have an embedded visualisation of what happens to all the elements inside the back stack (look at the row of orange boxes below the logo). ## Constructing the back stack As the back stack can never be empty, it's required to define an initial target. ```kotlin class BackStack( initialElement: NavTarget, savedStateMap: SavedStateMap?, // Optional parameters are omitted ) ``` ## Default on screen resolution As a default, only the active element is considered on screen. ```kotlin object BackStackOnScreenResolver : OnScreenStateResolver { override fun isOnScreen(state: State): Boolean = when (state) { State.CREATED, State.STASHED, State.DESTROYED -> false State.ACTIVE -> true } } ``` ## Default transition handlers #### BackStackFader `rememberBackstackFader()` Adds simple cross-fading transitions #### BackStackSlider `rememberBackstackSlider()` Adds horizontal sliding transitions so that the `ACTIVE` element is in the center; other states are animated from / to the left or the right edge of the screen. ## Operations #### Push `backStack.push(navTarget)` Effect on stack: ``` [A, B, C] + Push(D) = [A, B, C, D] ``` Transitions the active element `ACTIVE` -> `STASHED`. Adds a new element at the end of the stack with a `CREATED` -> `ACTIVE` transition. #### Replace `backStack.replace(navTarget)` Effect on stack: ``` [A, B, C] + Replace(D) = [A, B, D] ``` Transitions the active element `ACTIVE` -> `DESTROYED`, which will be removed when the transition finishes. Adds a new element at the end of the stack with a `CREATED` -> `ACTIVE` transition. #### Pop `backStack.pop(navTarget)` Effect on stack: ``` [A, B, C] + Pop = [A, B] ``` Transitions the active element `ACTIVE` -> `DESTROYED`, which will be removed when the transition finishes. Transitions the last stashed element `STASHED` -> `ACTIVE`. #### Single top `backStack.singleTop(navTarget)` Effect on stack: depends on the contents of the stack: ``` [A, B, C, D] + SingleTop(B) = [A, B] // of same type and equals, acts as n * Pop [A, B, C, D] + SingleTop(B') = [A, B'] // of same type but not equals, acts as n * Pop + Replace [A, B, C, D] + SingleTop(E) = [A, B, C, D, E] // not found, acts as Push ``` ## Back press strategy You can override the default strategy in the constructor. You're not limited to using the provided classes, feel free to implement your own. ```kotlin class BackStack( /* ... */ backPressHandler: BackPressHandlerStrategy = PopBackPressHandler(), /* ... */ ) ``` #### PopBackPressHandler The default back press handling strategy. Runs a `Pop` operation. #### DontHandleBackPress Serves as a no-op. ## Operation strategy You can override the default strategy in the constructor. You're not limited to using the provided classes, feel free to implement your own. ```kotlin class BackStack( /* ... */ operationStrategy: OperationStrategy = ExecuteImmediately(), /* ... */ ) ``` #### ExecuteImmediately The default strategy. New operations are executed without any questions, regardless of any already running transitions. #### FinishTransitionsOnNewOperation All running transitions are abruptly finished when a new one is started #### QueueOperations The new operation is queued and executed after the current one finishes #### IgnoreIfThereAreUnfinishedTransitions Runs the new one only if there are no transitions happening currently; ignore and discard it otherwise