Flutter屏幕适配插件adaptix的使用
Flutter屏幕适配插件adaptix的使用
adaptix
是一个功能强大且轻量级的软件包,用于构建响应式和自适应的应用程序。
使用
初始化
- 将你的小部件子树(通常是应用的起点)包装在
AdaptixInitializer
中,并将AdaptixConfigs
的实例传递给configs
参数。
AdaptixInitializer(
configs: const AdaptixConfigs.canonical(),
builder: (context) {
return MaterialApp(
home: ...,
);
},
);
- 通过
BuildContext
访问数据。你可以使用Adaptix.of(context)
访问AdaptixConstraints
,或者使用为语义设计的扩展方法。
AdaptixInitializer(
configs: const AdaptixConfigs.canonical(),
builder: (context) {
// 访问adaptix
print(Adaptix.of(context));
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
color: Colors.red,
width: 50.adaptedPx(context),
height: 50.adaptedPx(context),
child: Text('${50.adaptedPx(context).round()} px'),
),
],
),
),
),
);
},
);
响应式断点
ResponsiveBreakpoint
实例表示一种布局模式的起始点,当设备布局发生变化时,Adaptix
将切换到该断点。这些断点通过其 templateDeviceWidth
字段区分。在这个软件包中,ResponsiveBreakpoint
的 templateDeviceWidth
是设备宽度,用于决定是否使用该断点来切换布局。
如果在配置中设置了 DeviceBreakpointDecisionStrategy.useOriginalWidth
,则会使用设备的实际宽度进行比较;否则,如果设置了 DeviceBreakpointDecisionStrategy.useShortestSide
,则会选择设备的最短边进行比较。
如何决定使用哪个断点?
基本逻辑如下:
- 如果设备的最短边大于或等于某个断点的
templateDeviceWidth
并小于下一个断点的templateDeviceWidth
,则选择该断点。 - 如果设备的最短边小于第一个断点的
templateDeviceWidth
,则选择第一个断点。 - 如果设备的最短边大于最后一个断点的
templateDeviceWidth
,则选择最后一个断点。
自定义配置
你可以使用 AdaptixConfigs
的默认构造函数来自定义配置。
AdaptixConfigs(
/// 定义断点
/// 使用模板设备的宽度作为断点的templateDeviceWidth
breakpoints: const [
ResponsiveBreakpoint(templateDeviceWidth: 375, key: 'iphone7'),
ResponsiveBreakpoint(templateDeviceWidth: 414, key: 'iphone11'),
ResponsiveBreakpoint(templateDeviceWidth: 768, key: 'ipadMini'),
],
/// 定义每个断点的像素比例规则
pixelScaleRules: const {
'iphone7': 1,
'iphone11': 1.1,
'ipadMini': 1.2,
},
)
扩展方法
.adaptedPx
在 double
上
获取根据当前 Adaptix
断点缩放后的逻辑像素。
print(1.adaptedPx(context));
.widthFraction
在 double
上
给出设备宽度的百分比。
// 表示设备宽度的50%
print(50.widthFraction(context));
.heightFraction
在 double
上
给出设备高度的百分比。
// 表示设备高度的50%
print(50.heightFraction(context));
.shortestSideFraction
在 double
上
给出设备最短边的百分比。
// 表示设备最短边的50%
print(50.shortestSideFraction(context));
.longestSideFraction
在 double
上
给出设备最长边的百分比。
// 表示设备最长边的50%
print(50.longestSideFraction(context));
.orientationSwitch
在 context
上
返回根据当前方向的文本。
print(
context.orientationSwitch<String>(
onLandscape: 'Landscape text',
onPortrait: 'Portrait text'
)
);
.responsiveSwitch
在 context
上
如果你想根据当前 Adaptix
断点显示某些小部件或文本,可以使用此扩展方法。
AdaptixInitializer(
configs: AdaptixConfigs(
/// 定义断点
/// 使用模板设备的宽度作为断点的值
breakpoints: const [
ResponsiveBreakpoint(templateDeviceWidth: 375, key: 'iphone7'),
ResponsiveBreakpoint(templateDeviceWidth: 414, key: 'iphone11'),
ResponsiveBreakpoint(templateDeviceWidth: 768, key: 'ipadMini'),
],
/// 定义每个断点的像素比例规则
pixelScaleRules: const {
'iphone7': 1,
'iphone11': 1.1,
'ipadMini': 1.2,
},
),
builder: (context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
color: Colors.red,
width: 50.adaptedPx(context),
height: 50.adaptedPx(context),
child: Text(
context.responsiveSwitch(
const GenericResponsiveSwitchArgs<String>(
defaultValue: 'This is a default text',
rules: const {
'iphone7': 'Hello, I am a pattern based on width of iphone7',
'iphone11':
'Hello, I am a pattern based on dimensions of iphone11',
'ipadMini':
'Hello, I am a pattern based on dimensions of ipadMini',
},
),
),
),
),
],
),
),
),
);
},
);
注意:如果你使用了 AdaptixConfigs.canonical
,那么在调用 .responsiveSwitch
方法时需要传递 CanonicalResponsiveBreakpoint.createCanonicalSwitchArguments
参数。
context.responsiveSwitch(CanonicalResponsiveBreakpoint
.createCanonicalSwitchArguments<String>(
defaultValue: 'Some default text',
xSmall: 'Text of xSmall devices',
small: 'Text of small devices',
medium: 'Text of medium devices',
tablet: 'Text of tablets',
desktop: 'Text of desktop apps'));
最佳实践
建议使用值对象模式实现优雅的语义和可维护的架构。可以使用 Dart 2.17 提供的增强枚举来实现这一点。
enum MyResposivenessPattern implements ResponsiveBreakpoint {
iphone11(templateDeviceWidth: 414, pixelScale: 1.1),
iphone7(templateDeviceWidth: 375, pixelScale: 1),
ipadMini(templateDeviceWidth: 768, pixelScale: 1.12),
someDesktopDevice(templateDeviceWidth: 1024, pixelScale: 1.2);
static final myPixelScaleRules = {
for (var value in values) value.key: value.pixelScale,
};
@override
final double templateDeviceWidth;
final double pixelScale;
const MyResposivenessPattern(
{required this.templateDeviceWidth, required this.pixelScale});
@override
String get debugLabel => key;
@override
bool hasSameValueAs(ResponsiveBreakpoint other) =>
other.templateDeviceWidth == templateDeviceWidth;
@override
bool isSameAs(ArgsComparisonMixin other) {
return ResponsiveBreakpoint.breakpointEquality(
this,
other,
);
}
/// key 作为枚举元素的名称
@override
String get key => name;
static GenericResponsiveSwitchArgs<T> myResponsiveSwitchArguments<T>({
required T defaultValue,
T? iphone7Value,
T? iphone11Value,
T? ipadMiniValue,
T? someDesktopDeviceValue,
}) {
return GenericResponsiveSwitchArgs(
defaultValue: defaultValue,
rules: {
iphone7.key: iphone7Value ?? defaultValue,
iphone11.key: iphone11Value ?? defaultValue,
ipadMini.key: ipadMiniValue ?? defaultValue,
someDesktopDevice.key: someDesktopDeviceValue ?? defaultValue,
},
);
}
static AdaptixConfigs configs() => AdaptixConfigs(
breakpoints: MyResposivenessPattern.values,
pixelScaleRules: MyResposivenessPattern.myPixelScaleRules,
);
}
使用它的方式如下:
AdaptixInitializer(
configs: MyResposivenessPattern.configs(),
builder: (context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
color: Colors.red,
width: 50.adaptedPx(context),
height: 50.adaptedPx(context),
child: Text(context.responsiveSwitch(
MyResposivenessPattern.myResponsiveSwitchArguments<String>(
defaultValue: 'Unrecognized device pattern',
iphone7Value: 'iphone7 device pattern',
iphone11Value: 'iphone11 device pattern',
ipadMiniValue: 'ipadMini device pattern',
),
)),
),
SizedBox(
child: Text(context.orientationSwitch<String>(
onLandscape: 'Landscape text',
onPortrait: 'Portrait text',
)),
),
],
),
),
),
);
},
);
更多关于Flutter屏幕适配插件adaptix的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter屏幕适配插件adaptix的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于如何在Flutter项目中使用adaptix
插件进行屏幕适配,下面是一个具体的代码案例。adaptix
是一个流行的Flutter屏幕适配库,它可以帮助开发者轻松处理不同屏幕尺寸和分辨率的适配问题。
首先,确保你已经在pubspec.yaml
文件中添加了adaptix
依赖:
dependencies:
flutter:
sdk: flutter
adaptix: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来获取依赖。
接下来,在你的Flutter项目的入口文件(通常是main.dart
)中进行配置:
import 'package:flutter/material.dart';
import 'package:adaptix/adaptix.dart';
void main() {
// 初始化Adaptix
AdaptixConfig config = AdaptixConfig(
designWidth: 375, // 设计稿的宽度,单位px
designHeight: 667, // 设计稿的高度,单位px
);
Adaptix.init(context, config);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Adaptix Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 使用Adaptix的px方法将设计稿中的px转换为适配后的屏幕尺寸
double adaptedWidth = Adaptix.px(375); // 这将返回屏幕宽度的一半(假设屏幕宽度为750px)
double adaptedHeight = Adaptix.px(100); // 这将根据屏幕宽度比例缩放高度
return Scaffold(
appBar: AppBar(
title: Text('Adaptix Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: adaptedWidth,
height: adaptedHeight,
color: Colors.blue,
child: Center(
child: Text(
'Adapted Box',
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(height: Adaptix.px(20)), // 20px的间距,适配后
Text(
'Screen Width: ${Adaptix.screenWidth}\nScreen Height: ${Adaptix.screenHeight}',
style: TextStyle(fontSize: Adaptix.sp(16)), // 16sp的文字大小,适配后
),
],
),
),
);
}
}
在这个示例中,我们做了以下几件事情:
- 初始化Adaptix:在
main
函数中,通过Adaptix.init
方法传入设计稿的宽度和高度来初始化Adaptix。 - 使用Adaptix的方法:在
MyHomePage
中,我们使用Adaptix.px
方法将设计稿中的px值转换为适配后的屏幕尺寸值,使用Adaptix.sp
方法将sp值转换为适配后的文字大小。 - 展示适配后的UI:创建了一个容器和一个文本,容器的尺寸和文字的大小都是经过适配的。
这样,无论设备屏幕尺寸如何变化,UI都能保持与设计稿一致的比例和布局。
请确保你根据项目的实际需求调整设计稿的宽度和高度,以及其他具体的UI元素尺寸。