Custom ScreenSwitcher for Flutter

35 Views Asked by At

Is there any possible way to control the state of the Widgets outside of them? I've tried using global keys, but is there anything easier to use? I've read that using of the global keys is not the best way from the optimization side. I don't want to use Flutter navigation utils, but, if I will if I have no choice, since I have too many problems with global keys now.

I tried to implement the following ScreenSwitcher with screens.dart file, but there are too many stupid moments, in my opinion.
This file contains all of my screens, with globalKeys and end actions for anims, that deletes my widget from the stack

screens.dart:

GlobalKey<ScreenSwitcherState> stackSwitcherStateKey = GlobalKey();

enum ScreenUniqueID {
  uiLauncherLogo,
  uiLauncherMain,
  uiLauncherModal,
  uiLauncherSettings,
  uiLauncherServers,
  uiLauncherSocial,
  uiLauncherAccount,
}

GlobalKey<LauncherMainScreenState> screenKeyLauncherMain =
    GlobalKey<LauncherMainScreenState>();
GlobalKey<LauncherModalScreenState> screenKeyLauncherModal =
    GlobalKey<LauncherModalScreenState>();
GlobalKey<LauncherSettingsScreenState> screenKeyLauncherSettings =
    GlobalKey<LauncherSettingsScreenState>();
GlobalKey<LauncherLogoScreenState> screenKeyLauncherLogo =
    GlobalKey<LauncherLogoScreenState>();
GlobalKey<LauncherServersScreenState> screenKeyLauncherServers =
    GlobalKey<LauncherServersScreenState>();
GlobalKey<LauncherSocialBonusScreenState> screenKeyLauncherSocial =
    GlobalKey<LauncherSocialBonusScreenState>();
GlobalKey<LauncherAccountScreenState> screenKeyLauncherAccount =
GlobalKey<LauncherAccountScreenState>();

var screensDb = <ScreenObject>[
  ScreenObject(
      key: screenKeyLauncherLogo,
      widget: LauncherLogoScreen(
        key: screenKeyLauncherLogo,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherLogo);
        },
      )),
  ScreenObject(
      key: screenKeyLauncherMain,
      widget: LauncherMainScreen(
        key: screenKeyLauncherMain,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherMain);
        },
      ).animate(effects: [const FadeEffect()])),
  ScreenObject(
      key: screenKeyLauncherModal,
      widget: LauncherModalScreen(
        modalKey: screenKeyLauncherModal,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherModal);
        }, positiveText: '', negativeText: '', dialogText: '', svgAssetName: '', onPositiveButtonAction: (){}, onNegativeButtonAction: (){}, negativeVisible: true,
      ).animate(effects: [const FadeEffect()])),
  ScreenObject(
      key: screenKeyLauncherSettings,
      widget: LauncherSettingsScreen(
        key: screenKeyLauncherSettings,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherSettings);
        },
      )),
  ScreenObject(
      key: screenKeyLauncherServers,
      widget: LauncherServersScreen(
        key: screenKeyLauncherServers,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherServers);
        },
      )),
  ScreenObject(
      key: screenKeyLauncherSocial,
      widget: LauncherSocialBonusScreen(
        key: screenKeyLauncherSocial,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherSocial);
        },
      )),
  ScreenObject(
      key: screenKeyLauncherAccount,
      widget: LauncherAccountScreen(
        key: screenKeyLauncherAccount,
        onAnimationEndAction: () {
          stackSwitcherStateKey.currentState
              ?.removeScreen(screenKeyLauncherAccount);
        },
      )),
];

screen_switcher.dart:

class ScreenSwitcher extends StatefulWidget {
  Function onWidgetLoaded;

  final GlobalKey<ScreenSwitcherState> stackSwitcherStateKey;

  ScreenSwitcher(this.onWidgetLoaded, this.stackSwitcherStateKey)
      : super(key: stackSwitcherStateKey);

  @override
  ScreenSwitcherState createState() => ScreenSwitcherState();
}

class ScreenSwitcherState extends State<ScreenSwitcher> {
  var activeScreens = <ScreenObject>[];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    widget.onWidgetLoaded();
    print("onWidgetLoaded");
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [Stack(children: activeScreens.map((e) => e.widget).toList())],
    );
  }

  Future<void> removeScreen(Key key) async {
    setState(() {
      var listToRemove = [];
      for (var element in activeScreens) {
        if (element.key == key) {
          listToRemove.add(element);
        }
      }
      activeScreens.removeWhere((element) => listToRemove.contains(element));
    });
  }

  void showScreen(int ui) async {
    setState(() {
      ScreenObject screen = screensDb.elementAt(ui);
      if(ui == ScreenUniqueID.uiLauncherMain.index){
        GlobalKey<LauncherMainScreenState> screenKeyLauncherMain1 = GlobalKey<LauncherMainScreenState>();

        screen = ScreenObject(
            key: screenKeyLauncherMain1,
            widget: LauncherMainScreen(
              key: screenKeyLauncherMain1,
              onAnimationEndAction: () {
                stackSwitcherStateKey.currentState
                    ?.removeScreen(screenKeyLauncherMain1);
              },
            ).animate(effects: [const FadeEffect()]));

        screensDb[ScreenUniqueID.uiLauncherMain.index] = screen;

      }
      if(ui == ScreenUniqueID.uiLauncherAccount.index){
        GlobalKey<LauncherAccountScreenState> screenKeyLauncherAcc = GlobalKey<LauncherAccountScreenState>();

        screen = ScreenObject(
            key: screenKeyLauncherAcc,
            widget: LauncherAccountScreen(
              key: screenKeyLauncherAcc,
              onAnimationEndAction: () {
                stackSwitcherStateKey.currentState
                    ?.removeScreen(screenKeyLauncherAcc);
              },
            ).animate(effects: [const FadeEffect()]));

        screensDb[ScreenUniqueID.uiLauncherAccount.index] = screen;
      }
      if (activeScreens.any((element) => screen.key == element.key)) {
        return;
      }
      activeScreens.add(screen);
    });
  }

  void showModal(
      String positiveText,
      String negativeText,
      String dialogText,
      String svgAssetName,
      Function onPositiveButtonAction,
      Function onNegativeButtonAction,
      bool negativeVisible) async {

    GlobalKey<LauncherModalScreenState> globalKey = GlobalKey();

    screensDb[ScreenUniqueID.uiLauncherModal.index] = ScreenObject(
        key: globalKey,
        widget: LauncherModalScreen(
          onAnimationEndAction: () {
            stackSwitcherStateKey.currentState?.removeScreen(globalKey);
          },
          modalKey: globalKey,
          positiveText: positiveText,
          negativeText: negativeText,
          dialogText: dialogText,
          svgAssetName: svgAssetName,
          onPositiveButtonAction: onPositiveButtonAction,
          onNegativeButtonAction: onNegativeButtonAction,
          negativeVisible: negativeVisible,
        ));

    ScreenObject screen =
        screensDb.elementAt(ScreenUniqueID.uiLauncherModal.index);

    setState(() {
      activeScreens.add(screen);
    });
  }

  void hideScreen(int ui) {
    print("hideScreen " + ui.toString());

    ScreenObject screen = screensDb.elementAt(ui);
    setState(() {
      (screen.key.currentState as WidgetUI).removeView();
    });
  }
}
0

There are 0 best solutions below