StateGraph Architecture – Transitions

Experimental: Further advancing StateGraph Architecture, this delves into state transitions. Please read the first post, if you haven’t already, otherwise this isn’t going to make much sense.

Moving between states has been covered previously, now lets delve into transitions. This is doing state or page transitions from the ground up, with no Navigator, as I am not using the Material Widgets.

Page Transitions

State Graph doesn’t have pages, only states, but in this example, we say that 2 states represent 2 different pages and as we move from one to the other, we want a nice transition.

Here I create a slide transition, that horizontally slides 2 widgets (or pages in this case).

abstract class Transition {
  Widget create(Animation animation, Widget from, Widget to, bool reverse);
}

class PageSlideTransition implements Transition {
  Widget create(Animation animation, Widget from, Widget to, bool reverse) {
    return Stack(textDirection: TextDirection.ltr, children: [
      SlideTransition(
        position: Tween(
          begin: Offset.zero,
          end: Offset(reverse ? 1.0 : -1.0, 0.0),
        ).animate(animation),
        child: from,
      ),
      SlideTransition(
        position: Tween(
          begin: Offset(reverse ? -1.0 : 1.0, 0.0),
          end: Offset.zero,
        ).animate(animation),
        child: to,
      )
    ]);
  }
}

From here, I added a Transition variable to the State, that I added as such.

static WidgetState _build(IState state) {
    // Compiled state management
    if (state.branch == Branch.login)
      return WidgetState(LoginNode.render(state),
          transition: PageSlideTransition());

    return WidgetState(_unknownState());
  }

The LoginNode is renderered as a Widget, and a container called WidgetState, will pass this and the transition to the RenderGraph.

RenderGraph

In the RenderGraph, I check the WidgetState to see if there is a Transition. If so, I will use this Transition to move between the new states.

if (buildState.transition is PageSlideTransition) {
        _animationController = new AnimationController(
            vsync: _state, duration: const Duration(milliseconds: 1000));

        var transition = (buildState.transition as PageSlideTransition)
            .create(_animationController, _current, buildState.widget, state.reverse);

        _current = buildState.widget;

        _animationController.forward();

        state.reverse = false;

        return transition;
      } else {
        return buildState.widget;
      }

 

Back Button

To reverse the state when pressing the back button, I attached to the WidgetBindings. Then called StateGraph.reverse(), when the back button was pressed.

class _AppState extends State
    with TickerProviderStateMixin, WidgetsBindingObserver {
  _AppState() {
    RenderGraph.initialize(this);
    StateGraph.initialize(() => setState(() => {}));
  }

  @override
  Widget build(BuildContext context) {
    return RenderGraph.build(StateGraph.current());
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  didPopRoute() {
    StateGraph.reverse();
    return Future.value(true);
  }
}

Summary

With complete control of the transition of states, you are open to perform any transition. You are not limited by platform. Make your widgets spin, explode, change color and oscillate off the screen if you want to.

If you want the source code for this post please see – Source Code (v3): StateGraph

Mobile Developer, Microsoft & Xamarin MVP

Share on
© 2018 Adam Pedley