首页 > 解决方案 > 制作自适应颤振应用程序的最佳方法是什么?

问题描述

我已经制作了很多颤振应用程序,但我不太确定制作响应式应用程序的最佳方式是什么。我目前正在做的是我正在制作相对于屏幕大小的所有小部件。

例如,要渲染一个容器,而不是放置一个固定大小:

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

因此,我所有的小部件都不会有不同的断点,而是与它们使用的任何手机相关。这是正确的做法吗?

如果我应该使用断点,移动断点应该是什么?我知道对于一个网站,我会为手机、Ipad、笔记本电脑、台式机等设置断点,但小型手机、中型手机和大型手机的断点是什么?谢谢!

标签: androidiosflutterresponsive-designresponsive

解决方案


在 Flutter 网页上,您可以找到一篇关于如何构建自适应 Flutter 应用程序的精彩文章(请参阅此处)。

与基于屏幕的断点方法类似的另一个选项是抽象工厂模式

为了实现抽象工厂模式,您首先需要一个抽象工厂和一个类,它决定了可用的屏幕尺寸(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;
  }
}

之后你必须实现具体的工厂(我将在一个例子中展示):

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

比您的样式需要一个抽象类。这可能看起来像这样:

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;
}

它的具体实现如下所示:

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;
}

在视图中使用它看起来像这样:

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();
  }


}

IMySize 和 IMyFactory 看起来像这样:

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.


推荐阅读