What's the best way to make a adaptive flutter app?

349

on the flutter web page you can find a nice article about how to build an adaptive flutter application (see here).

Another option, which is simular to the screen-based breakpoint approach is the abstract factory pattern.

In order to implement the abstract factory pattern you need at first an abstract factory and a class, which determines the available screen size (AdaptivityWidget) :

abstract class IWidgetsFactory {

   // returns the factory regarding to the screen size
   static IWidgetsFactory getFactory(BuildContext context) {
    if (AdaptivityWidget.isTinyScreen(context)) {
      return TinyScreenFactory();
    } else if (AdaptivityWidget.isSmallScreen(context)) {
      return SmallScreenFactory();
    } else if (AdaptivityWidget.isMediumScreen(context)) {
      return MediumScreenFactory();
    } else {
      return LargeScreenFactory();
    }
  }

  // implement the abstract methods, which the concrete factories shall implement
  double getBurgerMenuIconSize();

  // and so on ...
}
/// [AdaptivityWidget] determines, which type of screen is available.
class AdaptivityWidget {

  /// Returns the current width depending on the current context.
  static double _getWidth(BuildContext context) {
    return MediaQuery.of(context).size.width;
  }

  /// Large screen is any screen whose width is more than 1200 pixels.
  static bool isLargeScreen(BuildContext context) {
    return _getWidth(context) >= 1200;
  }

  /// Medium screen is any screen whose width is less than 1200 pixels,
  /// and more than 799 pixels.
  static bool isMediumScreen(BuildContext context) {
    return _getWidth(context) >= 800 && _getWidth(context) < 1200;
  }

  /// Small screen is any screen whose width is less than 800 pixels,
  /// and more than 399.
  static bool isSmallScreen(BuildContext context) {
    return _getWidth(context) >= 400 && _getWidth(context) < 800;
  }

  /// Tiny Screen is any screen whose width is less than 400 pixels.
  static bool isTinyScreen(BuildContext context) {
    return _getWidth(context) < 400;
  }
}

Afterwards you have to implement the concrete factories (I will show that on one example):

/// Concrete factory for large screens.
class LargeScreenFactory extends IWidgetsFactory {
  /// Returns 48.0px.
  @override
  double getBurgerMenuIconSize() {
    return SizeT24S32M40L48().large;
  }
}

Than you require an abstract class for your styles. This could look like this:

abstract class IStyle {
  /// Parameter for [TinyScreenFactory]
  dynamic get tiny;

  /// Parameter for [SmallScreenFactory]
  dynamic get small;

  /// Parameter for [MediumScreenFactory]
  dynamic get medium;

  /// Parameter for [LargeScreenFactory]
  dynamic get large;
}

And a concrete implementation of that looks like this:

class SizeT24S32M40L48 implements IStyle {

  @override
  double get large => 48.0;

  @override
  double get medium => 40.0;

  @override
  double get small => 32.0;

  @override
  double get tiny => 24.0;
}

To use it in a view would look like this:

class View extends StatelessWidget implements IMyFactory, IMySize{
  @override
  Widget build(BuildContext context){
    return Icon(
      Icons.menu,
      size: getSize(getFactory(context)),
    );
  }
  
  /// Returns a widget factory.
  @override
  IWidgetsFactory getFactory(BuildContext context) {
    return IWidgetsFactory.getFactory(context);
  }

  /// Returns a single icon size.
  @override
  double getSize(IWidgetsFactory factory) {
    return factory.getBurgerMenuIconSize();
  }


}

Where IMySize and IMyFactory can look like this:

abstract class IMySize {
  double getSize(IWidgetsFactory factory);
}

abstract class IMyFactory {
  IWidgetsFactory getFactory(BuildContext context);
}

You can use the abstract factory pattern also in order to differ between Android and iOS in order to generate platform specific behaviour.

Share:
349
sammhung
Author by

sammhung

Updated on January 01, 2023

Comments

  • sammhung
    sammhung over 1 year

    I've made quite a few flutter apps, but I'm not too sure what's the best way to make a responsive app. What I am currently doing is I'm making all my widgets relative to the screeensize.

    For example, to render a container, instead of putting a fixed size:

    width: MediaQuery.of(context).size.width * 0.2;
    

    So instead of having different breakpoints all my widgets will be relative to whatever phone they are using. Is that the right way of doing it?

    If I should be using breakpoints, what should the mobile breakpoints be? I know that for a website I would do breakpoints for a phone, Ipad, Laptop, Desktop etc, but what are the breakpoints for a small phone, medium phone and large phone? Thanks!