Flutter自适应显示插件adaptive_display的使用
Flutter 自适应显示插件 adaptive_display
的使用
adaptive_display
BoxConstraints
的包装器,使其更加可控、更少缩进并可重用。
特性
在您的 Flutter 项目中使用此插件来:
- 自适应状态有状态小部件:适用于有状态小部件的自适应状态。
- 自适应无状态小部件:适用于无状态小部件的自适应状态。
- 自适应小部件:适用于无状态小部件的自适应小部件,具有
BoxConstrains
值。 - 自适应包裹小部件:适用于无状态小部件的自适应包裹小部件,具有
BoxConstrains
值。
开始使用
安装依赖
-
在
pubspec.yaml
文件中添加adaptive_display
依赖:dependencies: adaptive_display: latest_version
-
运行
flutter pub get
来安装依赖。 -
如果您的小部件使用了
StatelessWidget
,则将其替换为下面提供的小部件之一。如果您使用的是StatefulWidget
,可以将State
类切换到AdaptiveWrapState
。 -
享受定义项目的布局吧!
使用方法
该包向您的 Stateful
和 Stateless
小部件添加了一些构建器。
这些构建器有两种类型的 UI 定义:
- 默认构建。[自适应无状态小部件, 自适应小部件]
- 包裹构建。[自适应包裹状态, 自适应包裹小部件]
对于默认构建器,我们采用移动优先的方法,因此我们的构建方法是基础构建,然后是 xs,接着是 sm,依此类推。
对于包裹构建器,我们的构建方法会包裹所有内容,所以您应该首先定义 xs 并在构建方法中调用 [adaptive]
。
当您实例化这些小部件中的任何一个时,您可以获得五个可选的构建器,它们按顺序构建您的视图。
[@override](/user/override)
Widget xs(BuildContext context) { ... }
[@override](/user/override)
Widget sm(BuildContext context) { ... }
[@override](/user/override)
Widget md(BuildContext context) { ... }
[@override](/user/override)
Widget lg(BuildContext context) { ... }
[@override](/user/override)
Widget xl(BuildContext context) { ... }
注意:使用 AdaptiveWidget
和 AdaptiveWrapWidget
可以访问约束值 🤗
[@override](/user/override)
Widget xs(BuildContext context, BoxConstraints constraints) { ... }
自适应包裹状态用于有状态小部件
通过这个抽象小部件,您可以将自适应显示小部件与有状态小部件结合起来,只需添加包并切换 State
类到 AdaptiveWrapState
即可访问构建器。
class StatefulAdaptive extends StatefulWidget {
const StatefulAdaptive({super.key});
[@override](/user/override)
// ⬇ 在这里
State<StatefulAdaptive> createState() => _StatefulAdaptiveState();
}
// ⬇ 在这里
class _StatefulAdaptiveState extends AdaptiveWrapState<StatefulAdaptive> {
[@override](/user/override)
Widget build(BuildContext context) {
return adaptive; // 您应该在这里调用 [adaptive]。
// 您可以将其包装在任何小部件中。
// 在 [AdaptiveStateLessWidget] 中,[xs] 是默认小部件
}
[@override](/user/override)
// 通过使构建方法能够包裹逻辑,
// xs 方法成为强制性的,并且是第一个被调用的方法。
Widget xs(BuildContext context) { ... } // 创建自定义 UI
}
自适应无状态小部件
对于 AdaptiveStatelessWidget
,您应该将其从 StatelessWidget
替换。
class StateLessAdaptive extends AdaptiveStatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
... // 您不应该在这里调用 [adaptive]。
// 逻辑会在小部件树中自动应用,
// 在 [AdaptiveStatelessWidget] 中,[build] 是默认小部件
}
}
自适应小部件
它保持与 AdaptiveStatelessWidget
相同的逻辑,但在每个构造方法中,它允许我们访问约束值。
如果您决定在构建方法中调用 "adaptive"
,请务必小心。
class StateLessAdaptive extends AdaptiveWidget {
[@override](/user/override)
Widget xs(BuildContext context, BoxConstraints constraints) {
final text = 'XS! ${constraints.maxWidth} value';
return Center(child: Text(text, style: textStyle));
}
}
自适应包裹小部件
它保持与 AdaptiveWrapState
相同的逻辑,但适用于 StatelessWidget
。您也可以在构建方法中使用约束值。
配置
在此包中,默认值如下:
大小 | 宽度 |
---|---|
超小 (xs) | 480 px |
小 (sm) | 768 px |
中 (md) | 1024 px |
大 (lg) | 1440 px |
超大 (xl) | 1920 px |
您可以通过在 main
方法中调用 Adaptive.setDefault()
方法来更改断点。但是,在设置值时必须遵循某些规则。这些规则是:
- XL 必须大于 LG
- LG 必须大于 MD
- MD 必须大于 SM
- SM 必须大于 XS
- XS 必须大于 0
void main() {
Adaptive.setDefault(xs: 420.0, xl: 1820.0); // xs, sm, md, lg, xl
}
完整示例
import 'package:adaptive_display/adaptive_display.dart';
import 'package:flutter/material.dart';
import 'package:widget_adaptive/widgets/adaptive_colorful.dart';
import 'package:widget_adaptive/widgets/adaptive_stateful.dart';
import 'package:widget_adaptive/widgets/adaptive_stateless.dart';
import 'package:widget_adaptive/widgets/adaptive_widget.dart';
import 'package:widget_adaptive/widgets/adaptive_wrap.dart';
/// ⬇ 这里任何自适应小部件
class SelectorPage extends AdaptiveWrapWidget {
const SelectorPage({super.key});
[@override](/user/override)
// [build] 方法包裹所有定义的构建器
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('自适应显示小部件'),
),
body: Center(
/// ⬇ 这里是 [adaptive] 小部件
child: adaptive),
);
}
/// 在 [AdaptiveWrapWidget] 中 xs 成为强制性的
[@override](/user/override)
Widget xs(BuildContext context, BoxConstraints constraints) {
return ListView(
padding: const EdgeInsets.all(32),
children: [
ElevatedButton(
onPressed: () => _goToWidgetAdaptive(context),
child: const Text('自适应小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetWrap(context),
child: const Text('自适应包裹小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetStateless(context),
child: const Text('无状态小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetStateful(context),
child: const Text('有状态小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetColorful(context),
child: const Text('多彩小部件'),
),
],
);
}
// 从 sm 开始的所有构建器都是可选的,
// 如果它们未定义,则将采用其前一个构建器的值
[@override](/user/override)
Widget md(BuildContext context, BoxConstraints constraints) {
return Row(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.all(32),
children: [
ElevatedButton(
onPressed: () => _goToWidgetAdaptive(context),
child: const Text('自适应小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetWrap(context),
child: const Text('自适应包裹小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetStateless(context),
child: const Text('无状态小部件'),
),
const SizedBox(height: 16),
],
),
),
Expanded(
child: ListView(
padding: const EdgeInsets.all(32),
children: [
ElevatedButton(
onPressed: () => _goToWidgetStateful(context),
child: const Text('有状态小部件'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => _goToWidgetColorful(context),
child: const Text('多彩小部件'),
),
],
),
),
],
);
}
}
void _goToWidgetAdaptive(BuildContext context) {
Navigator.pushNamed(context, '/widget_adaptive');
}
void _goToWidgetStateless(BuildContext context) {
Navigator.pushNamed(context, '/widget_stateless');
}
void _goToWidgetStateful(BuildContext context) {
Navigator.pushNamed(context, '/widget_stateful');
}
void _goToWidgetWrap(BuildContext context) {
Navigator.pushNamed(context, '/widget_wrap');
}
void _goToWidgetColorful(BuildContext context) {
Navigator.pushNamed(context, '/widget_colorful');
}
final routes = {
'/': (context) => const SelectorPage(),
'/widget_adaptive': (context) => const WidgetAdaptive(),
'/widget_wrap': (context) => const WidgetWrapAdaptive(),
'/widget_stateless': (context) => const StateLessAdaptive(),
'/widget_stateful': (context) => const StatefulAdaptive(),
'/widget_colorful': (context) => const ColorfulAdaptive(),
};
void main() => runApp(const MainApp());
class MainApp extends StatelessWidget {
const MainApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: '自适应小部件',
color: Colors.black,
builder: (context, child) => child!,
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: routes,
);
}
}
更多关于Flutter自适应显示插件adaptive_display的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自适应显示插件adaptive_display的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用adaptive_display
插件来实现自适应显示的代码案例。adaptive_display
插件允许你根据设备的显示特性(如亮度模式、刷新率等)来调整你的应用界面。
首先,你需要在你的pubspec.yaml
文件中添加adaptive_display
依赖:
dependencies:
flutter:
sdk: flutter
adaptive_display: ^0.1.0 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中,你可以使用以下代码来检测并响应设备的显示特性变化。
import 'package:flutter/material.dart';
import 'package:adaptive_display/adaptive_display.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Adaptive Display Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AdaptiveDisplayScreen(),
);
}
}
class AdaptiveDisplayScreen extends StatefulWidget {
@override
_AdaptiveDisplayScreenState createState() => _AdaptiveDisplayScreenState();
}
class _AdaptiveDisplayScreenState extends State<AdaptiveDisplayScreen> with WidgetsBindingObserver {
AdaptiveDisplayMode? _currentDisplayMode;
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this);
_listenToAdaptiveDisplayModeChanges();
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
AdaptiveDisplay.instance?.stopListeningToDisplayModeChanges();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
// Optionally re-subscribe to changes if needed when the app is resumed
_listenToAdaptiveDisplayModeChanges();
}
}
void _listenToAdaptiveDisplayModeChanges() {
AdaptiveDisplay.instance?.listenToDisplayModeChanges((AdaptiveDisplayMode mode) {
setState(() {
_currentDisplayMode = mode;
});
});
// Initial check to set the state based on the current display mode
AdaptiveDisplay.instance?.getCurrentDisplayMode().then((mode) {
setState(() {
_currentDisplayMode = mode;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Adaptive Display Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Current Display Mode:',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 10),
Text(
_currentDisplayMode == null ? 'Unknown' : _currentDisplayMode!.toString(),
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
],
),
),
);
}
}
代码解释
-
依赖添加:在
pubspec.yaml
中添加adaptive_display
依赖。 -
初始化:在
initState
方法中,我们添加了WidgetsBinding观察者,并调用_listenToAdaptiveDisplayModeChanges
方法来开始监听显示模式的变化。 -
监听显示模式变化:
_listenToAdaptiveDisplayModeChanges
方法订阅了显示模式的变化,并在变化时更新状态。 -
获取当前显示模式:通过调用
AdaptiveDisplay.instance?.getCurrentDisplayMode()
获取当前的显示模式,并在组件首次加载时设置状态。 -
UI显示:在UI中,我们显示当前的显示模式。如果显示模式未知,则显示“Unknown”。
-
生命周期管理:在
dispose
方法中,移除WidgetsBinding观察者,并停止监听显示模式的变化。在didChangeAppLifecycleState
方法中,当应用恢复时,可以重新订阅显示模式的变化(如果需要)。
请确保你已经正确安装并配置了adaptive_display
插件,并根据需要调整代码中的细节。由于插件的版本和API可能会变化,请参考插件的官方文档获取最新的使用方法和API参考。