制作自适应 Flutter 应用程序的最佳方法是什么?
What's the best way to make a adaptive flutter app?
我已经制作了很多 Flutter 应用程序,但我不太确定制作响应式应用程序的最佳方式是什么。我目前正在做的是根据屏幕大小制作所有小部件。
例如,渲染一个容器,而不是放一个固定大小的:
width: MediaQuery.of(context).size.width * 0.2;
因此,我所有的小部件都将与它们使用的 phone 相关,而不是使用不同的断点。这是正确的做法吗?
如果我应该使用断点,移动断点应该是什么?我知道对于一个网站,我会为 phone、Ipad、笔记本电脑、台式机等设置断点,但是对于小型 phone、中型 phone 和大phone?谢谢!
在 flutter 网页上,您可以找到一篇关于如何构建自适应 flutter 应用程序的好文章(参见 here)。
另一个选项,类似于基于屏幕的断点方法
是 abstract factory pattern.
为了实现抽象工厂模式,你首先需要一个抽象工厂和一个class,它决定了可用的屏幕尺寸(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;
}
}
比起你的风格需要一个摘要class。这可能看起来像这样:
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);
}
您也可以使用抽象工厂模式来区分 Android 和 iOS 以生成特定于平台的行为。
我已经制作了很多 Flutter 应用程序,但我不太确定制作响应式应用程序的最佳方式是什么。我目前正在做的是根据屏幕大小制作所有小部件。
例如,渲染一个容器,而不是放一个固定大小的:
width: MediaQuery.of(context).size.width * 0.2;
因此,我所有的小部件都将与它们使用的 phone 相关,而不是使用不同的断点。这是正确的做法吗?
如果我应该使用断点,移动断点应该是什么?我知道对于一个网站,我会为 phone、Ipad、笔记本电脑、台式机等设置断点,但是对于小型 phone、中型 phone 和大phone?谢谢!
在 flutter 网页上,您可以找到一篇关于如何构建自适应 flutter 应用程序的好文章(参见 here)。
另一个选项,类似于基于屏幕的断点方法 是 abstract factory pattern.
为了实现抽象工厂模式,你首先需要一个抽象工厂和一个class,它决定了可用的屏幕尺寸(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;
}
}
比起你的风格需要一个摘要class。这可能看起来像这样:
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);
}
您也可以使用抽象工厂模式来区分 Android 和 iOS 以生成特定于平台的行为。