头图

foreword

flutter_smart_dialog related addresses: pub , github , web effect

An open source library, with continuous iterative optimization, will inevitably encounter a very painful problem

  • The original design was not very reasonable: many new features wanted to be added were hindered by this

To make the library more powerful and robust, a refactoring must be done

  • Because the refactoring involves the exposed API, everyone will encounter a more irritating problem: after updating the version, a large area of errors will be reported
  • I have been thinking about it for a long time. How can I help you to migrate quickly? Finally came up with a reasonable solution

For the changes of flutter_smart_dialog version 4.0, many of them are to solve the historical legacy that I have not considered before. The original intention of this library was mainly to solve the problem of loading and dialog penetration; now it is extended to: custom dialog, attach dialog, loading, toast , the initial design is really inadequate, the API in config is difficult to subdivide the functions of these four modules, and the design of some parameters is not reasonable based on the current functions and scenarios, etc.

I hope everyone can understand why I want to refactor 🥺, I am definitely not doing things 🥺

Quick Migration Guide

Compatible API (required) ⭐️

illustrate
  • The show method is fast compatible
 SmartDialog.compatible.show();
SmartDialog.compatible.showAttach();
SmartDialog.compatible.showLoading();
SmartDialog.compatible.showToast();
  • config fast compatible
 SmartDialog.compatible.config;

Added compatible intermediate variable, which can be quickly compatible with the changed parameters

Quick action
  • Quick migration using global replace function: SmartDialog.show ---> SmartDialog.compatible.show

    • Mac: command + shift + r
    • Windows: ctrl+shift+r

image-20220501230620406

  • Config: SmartDialog.config ---> SmartDialog.compatible.config

    • Mac: command + shift + r
    • Windows: ctrl+shift+r

image-20220501230830221

Parameter removal (required) ⭐️

  • Version 4.0 removed a small number of parameters
method illustrate
showLoading(...) Delete the background parameter (compatible is not compatible with this parameter)
showToast(...) Remove the alignment parameter (compatible with this parameter)
showAttach(...) Delete the highlight parameter (compatible with this parameter)
  • These parameters are deleted. When initializing custom loading and toast, you need to make a little adjustment
 void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage,
      // here
      navigatorObservers: [FlutterSmartDialog.observer],
      // here
      builder: FlutterSmartDialog.init(
        //default toast widget
        toastBuilder: (String msg) => CustomToastWidget(msg: msg),
        //default loading widget
        loadingBuilder: (String msg) => CustomLoadingWidget(msg: msg),
      ),
    );
  }
}
illustrate

background and alignment these two parameters are really useless, the frequency used is too low

Generally, the toast and loading styles are customized, and you can draw as you want; if you simply use toast and loading, these two parameters cannot achieve a strong custom effect, which is too cumbersome and simply deleted.

Parameter name change (optional)

Through the above 兼容API and 参数移除 you can complete the migration

Here I will write down the changed parameter names completely, you can compare them

original parameter name change parameter name
widget builder: Align with the routing dialog parameter (see the description of the builder parameter below for details)
isLoading / isLoadingTemp animationType: It is convenient to expand various animation types later
isPenetrate / isPenetrateTemp usePenetrate: true (click events will penetrate the background), false (do not penetrate)
isUseAnimation / isUseAnimationTemp useAnimation: true (use animation), false (do not use)
clickBgDismiss / clickBgDismissTemp clickMaskDismiss: true (close the dialog after clicking on the mask), false (do not close)
animationDuration / animationDurationTemp animationTime: animation duration
alignmentTemp alignment: controls the position of the pop-up window
maskColorTemp maskColor: mask color
maskWidgetTemp maskWidget: Highly customizable mask
debounceTemp debounce: Anti-shake function
time(showToast) displayTime: toast display time
type(showToast) displayType: Multiple types of toast display logic

Builder parameter description (important)

Version 4.0 has made a lot of changes to custom control parameters

  • old version
 SmartDialog.show(
  widget: Container(
    height: 80,
    width: 180,
    decoration: BoxDecoration(
      color: Colors.black,
      borderRadius: BorderRadius.circular(10),
    ),
    alignment: Alignment.center,
    child: Text(
      'easy custom dialog',
      style: TextStyle(color: Colors.white),
    ),
  ),
);
  • Version 4.0
 SmartDialog.show(builder: (context) {
  return Container(
    height: 80,
    width: 180,
    decoration: BoxDecoration(
      color: Colors.black,
      borderRadius: BorderRadius.circular(10),
    ),
    alignment: Alignment.center,
    child: Text(
      'easy custom dialog',
      style: TextStyle(color: Colors.white),
    ),
  );
});

Although this change will make it a little more troublesome to use, it is very important.

  • The first is to align with the api of the routing dialog, and the custom control parameters of the routing dialog are also builder
  • Then solve the problem of dynamic refresh of the custom dialog itself: the custom layout has TextField, when the keyboard pops up, the custom dialog layout can dynamically adjust the distance (need to use the corresponding widget)

What's New in Version 4.0

Powerful Config

  • You can use config to get whether the dialog exists
 // 自定义dialog,attach或loading,是否存在在界面上
SmartDialog.config.isExist;
// 自定义dialog或attach是否存在在界面上
SmartDialog.config.isExistDialog;
// loading是否存在界面上
SmartDialog.config.isExistLoading;
// toast是否存在在界面上
SmartDialog.config.isExistToast;
  • config can control show, showAttach, showLoading, showToast and other pop-up windows in more detail

    • The default parameters of SmartConfigXxx() are all set by me after deep thinking, and no additional settings are required if there are no special requirements.
    • If you do not need to customize the config value, the initialization code below does not need to be written
 SmartDialog.config
  ..custom = SmartConfigCustom()
  ..attach = SmartConfigAttach()
  ..loading = SmartConfigLoading()
  ..toast = SmartConfigToast();
  • You can customize the values in any config to meet the corresponding needs

    • The code below is to demonstrate custom parameters
    • You can set as needed
 SmartDialog.config
  ..custom = SmartConfigCustom(
    maskColor: Colors.black.withOpacity(0.35),
    useAnimation: true,
  )
  ..attach = SmartConfigAttach(
    animationType: SmartAnimationType.scale,
    usePenetrate: false,
  )
  ..loading = SmartConfigLoading(
    clickMaskDismiss: false,
    leastLoadingTime: const Duration(milliseconds: 0),
  )
  ..toast = SmartConfigToast(
    intervalTime: const Duration(milliseconds: 100),
    displayTime: const Duration(milliseconds: 2000),
  );

bindPage

illustrate

The meaning of this parameter is to bind the SmartDialog to the page: if the page is jumped on the SmartDialog

  • Binding SmartDialog to the current page will automatically hide
  • When back to the binding page, the SmartDialog will show

Regarding the problem of jumping pages on the Dialog, the version before 4.0 can be solved by using the useSystem parameter

  • When using the useSystem parameter, the essence is to use the built-in dialog as the carrier, so that you can interact with the page reasonably
  • 但是因为自带dialog的各种局限,使用useSystem时: usePenetratetagKeepSinglepermanent all banned

The logic of bindPage introduced in version 4.0 can avoid various restrictions when using useSystem

bindPage is enabled by default (can be configured in config), and can also be manually disabled or enabled when using show and showAttach; in special business scenarios, use bindPage and useSystem Just

Effect
  • Write a demo, this is the normal operation of jumping pages on the pop-up window
 void _dialogBindPage() async {
  var index = 0;
  Function()? showDialog;

  toNewPage(bool useSystem) async {
    Get.to(
      () {
        return Scaffold(
          appBar: AppBar(title: Text('New Page ${++index}')),
          body: Container(
            color: randomColor(),
            alignment: Alignment.center,
            child: ElevatedButton(
              onPressed: () => showDialog?.call(),
              child: Text('test bindPage $index'),
            ),
          ),
        );
      },
      preventDuplicates: false,
    );
  }

  showDialog = () {
    SmartDialog.show(builder: (_) {
      return Container(
        width: 300,
        height: 170,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(20),
        ),
        child: ElevatedButton(
          onPressed: () => toNewPage(false),
          child: Text('test bindPage $index'),
        ),
      );
    });
  };

  showDialog();
}
  • to see the effect

    • To be honest, the effect is silky without the useSystem function
    • But bindPage also solves the problem of jumping pages on the pop-up window, while retaining functions such as usePenetrate, tag, KeepSingle, permanent, etc.
    • Everyone needs to use

bindPage

Carry data when closing popup

This function is closed with flutter routing, and the function of carrying return data is aligned

  • Take a look at the demo: Click the show result button to close the pop-up window and return the data in the input box
 void _dialogCarryResult() async {
  var result = await SmartDialog.show(builder: (_) {
    var message = '';
    return Container(
      width: 300,
      height: 170,
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Column(mainAxisSize: MainAxisSize.min, children: [
        Container(
          width: 100,
          margin: EdgeInsets.only(bottom: 30),
          child: TextField(onChanged: (msg) => message = msg),
        ),
        ElevatedButton(
          onPressed: () => SmartDialog.dismiss(result: message),
          child: Text('show result'),
        )
      ]),
    );
  });

  SmartDialog.showToast("$result");
}
  • Effect

carryResult

Persistent Dialog

Set the permanent parameter to true, the opened dialog will become a permanent dialog, and all the closing operations (returning events, routing pop, clicking on the mask, etc.) inside the framework will be invalid, and only manual closure

Please use this function in combination with actual business scenarios and do not abuse it

  • Open a persistent dialog
 SmartDialog.show(
  permanent: true,
  usePenetrate: true,
  builder: (_) => Container(width: 150, height: 150, color: Colors.black),
);
  • Close the permanent dialog
 SmartDialog.dismiss(force: true);
  • Take a look at the demo
 void _dialogPermanent() async {
  openPermanentDialog() {
    SmartDialog.show(
      permanent: true,
      alignment: Alignment.centerRight,
      usePenetrate: true,
      clickMaskDismiss: false,
      builder: (_) {
        return Container(
          width: 150,
          height: double.infinity,
          alignment: Alignment.center,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(20),
              bottomLeft: Radius.circular(20),
            ),
            boxShadow: [
              BoxShadow(color: Colors.grey, blurRadius: 8, spreadRadius: 0.2)
            ],
          ),
          child: Text('permanent dialog'),
        );
      },
    );
  }

  SmartDialog.show(builder: (_) {
    return Container(
      width: 300,
      height: 170,
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(20),
      ),
      child: Wrap(spacing: 20, children: [
        ElevatedButton(
          onPressed: () => openPermanentDialog(),
          child: Text('open'),
        ),
        ElevatedButton(
          onPressed: () => SmartDialog.dismiss(force: true),
          child: Text('close'),
        )
      ]),
    );
  });
}
  • Effect: You can see the pop route, click on the mask and return events, can not be closed permanent dialog

permanentDialog

Minimum load time

There is a leastLoadingTime parameter in loading in config, which can control the minimum loading time

This function is to solve the problem that the interface request is too fast, causing the loading pop-up window to flash by.

  • Use: Please set appropriate data for this parameter in combination with the actual business scenario. The default value of leastLoadingTime is 0 seconds.

    • It is only for demonstration here, and config.loading is reassigned here. Generally, it is recommended to set the parameters in the initialization position of the app.
    • Call dismiss immediately after showLoading(), and loading will flash by
    • If the leastLoadingTime is set to 2 seconds, the loading will be forced to wait for two seconds before the dismiss will take effect.
 void _loadingLeastTime() async {
  SmartDialog.config.loading = SmartConfigLoading(
    leastLoadingTime: const Duration(seconds: 2),
  );
  SmartDialog.showLoading();
  SmartDialog.dismiss();
  SmartDialog.config.loading = SmartConfigLoading();
}
  • Effect

leastTime

Continuous toast display interval time

When multiple toasts are displayed continuously, the previous toast and the next toast display no interval time, which looks a bit awkward

Here, a SmartConfigToast intervalTime parameter is added to ---742f2f2221158cbcbb1c47da0ffe53dd--- to control the interval time

The default intervalTime is already a reasonable parameter, if it is unnecessary, it is best not to change it

  • Take a look at the effect, just for demonstration, intervalTime value is set slightly larger
 void _toastIntervalTime() async {
  SmartDialog.config.toast = SmartConfigToast(
    intervalTime: const Duration(milliseconds: 800),
  );
  for (var i = 0; i < 3; i++) {
    SmartDialog.showToast("toast $i").then((value) {
      if (!SmartDialog.config.isExistToast) {
        SmartDialog.config.toast = SmartConfigToast();
      }
    });
  }
}
  • renderings

intervalTime

Summarize

SmartDialog 4.0 version is a very important version, marking SmartDialog bid farewell to the green and mature

After this reconstruction, I also have the confidence to face more complex business scenarios and carry out various expansions.

I have done a lot of thinking about this reconstruction, and I am very grateful to everyone for giving me a variety of issues , you have inspired me!

img


小呆呆666
177 声望1.1k 粉丝

Android Flutter