Flutter界面适配与布局辅助插件flutter_fit_utils_ui的使用
Flutter界面适配与布局辅助插件flutter_fit_utils_ui的使用
flutter_fit_utils_ui
是一个用于加速开发并提高效率的 Flutter 包。该包提供了超过15个预构建的组件,使得在几行代码内即可使用它们。
功能
- FitText: 使用单行代码创建标题、标题、正文文本和提示。
- FitLoadingIndicator: 自动对齐的圆形加载指示器,始终适应您的应用程序主题。
- FitTextIcon: 简单地将图标与文本配对或反之亦然。
- FitLoadingHandler: 用于阻止输入并显示小部件正在加载。
- FitDiaporama: 可自定义的幻灯片,接受任何类型的图像。
- FitImageCard: 背景图像的卡片。无论使用什么图像,卡片上的文本总是可读的。
- FitButton: 简化按钮创建,无需重复代码。
- FitTextInput:
TextFormField
的精美包装。 - FitChips: 可以用作单选按钮的芯片。
- FitRadioCards: 美丽的卡片可以用作单选按钮。
- FitSwipeable: 简单易用的可滑动组件。
- FitSettings: 快速创建设置页面。
- FitForm: 使用更少的代码创建表单。
- FitMenu: 简单地创建美观的抽屉菜单。
- FitSort: 提供预先构建和可定制的排序算法。
- FitRuleValidator: 可视化步骤/规则的完成情况。
- FitDialog: 使用
FitDialog.show()
轻松显示对话框。
示例图片
开始使用
- 打开您的
pubspec.yaml
文件。 - 在
dependencies
下添加以下行:
flutter_fit_utils_ui: ^1.2.6
- 运行
flutter pub get
来获取依赖项。
使用方法
FitTheme 小部件
要更好地控制 fit
组件,可以将 FitTheme
小部件包裹在您的组件树周围。这个类允许您更改以下属性:
- 所有
FitText
的基本文本样式。 - 加载指示器的大小。
FitTextIcon
的主题数据。FitLoadingHandler
的加载行为。- 基本页面边距。
- 基本圆角半径。
这些属性被此包提供的不同小部件使用。
其他小部件
所有小部件都很容易使用,并且只需几行代码即可使用它们。例如,这是一个如何调用 FitText
的示例:
FitText.headline("Your Headline Here")
要了解其他可用的小部件,请查看示例文件 example/main.dart
。这个示例涵盖了所有可用的小部件。
完整示例代码
import 'package:flutter/material.dart';
import 'package:flutter_fit_utils_ui/flutter_fit_utils_ui.dart';
import 'package:google_fonts/google_fonts.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return FitTheme(
baseTextStyle: GoogleFonts.overpass(),
pageMargin: const EdgeInsets.all(12),
child: Builder(builder: (context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: FitTheme.of(context)!.innerRadius,
),
)),
home: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const FitText("flutter_fit_utils_ui"),
),
body: Builder(builder: (context) {
return Container(
margin: const EdgeInsets.only(top: 12, left: 12),
child: SingleChildScrollView(
child: Column(
children: [
const ExpansionTile(
title: FitText.title("FitText"),
children: [
FitText.headline("Headline"),
FitText.title("Title"),
FitText.body("Body",
style: TextStyle(color: Colors.purple)),
FitText.button("Button",
style: TextStyle(color: Colors.black)),
FitText.hint("Hint"),
],
),
ExpansionTile(
title: const FitText.title("FitLoadingIndicator"),
children: [
const FitText.body("Default"),
const FitLoadingIndicator(),
const SizedBox(height: 12),
const FitText.body(
"Customize it with ProgressIndicatorThemeData"),
Theme(
data: ThemeData(
progressIndicatorTheme:
const ProgressIndicatorThemeData(
color: Colors.red,
)),
child: const FitLoadingIndicator(
size: Size(25, 25))),
const SizedBox(height: 12),
const FitText.body("Change the alignment"),
const FitLoadingIndicator(
alignment: Alignment.centerLeft),
],
),
const ExpansionTile(
title: FitText.title("FitTextIcon"),
children: [
FitText.body("Default"),
FitTextIcon(
text: FitText.body("Information"),
icon: Icon(Icons.abc),
),
SizedBox(height: 12),
FitText.body("Custom"),
FitTextIcon(
text: FitText.body("Information"),
icon: Icon(Icons.book),
themeData: FitTextIconThemeData(
spacing: 12,
contentOrder: TextIconOrder.ti,
),
),
],
),
const ExpansionTile(
title: FitText.title("FitLoadingHandler"),
children: [
LoadingHandlerExample(),
],
),
ExpansionTile(
title: const FitText.title("FitDiaporama"),
children: [
SizedBox(
height: 100,
width: MediaQuery.of(context).size.width,
child: const FitDiaporama(
images: [
NetworkImage(
"https://avatars.githubusercontent.com/u/14101776?s=280&v=4"),
NetworkImage(
"https://upload.wikimedia.org/wikipedia/commons/thumb/4/44/Google-flutter-logo.svg/2560px-Google-flutter-logo.svg.png"),
],
),
),
],
),
ExpansionTile(
title: const FitText.title("FitImageCard"),
children: [
Container(
margin: const EdgeInsets.all(12),
child: FitImageCard(
onTap: () {},
image: const NetworkImage(
"https://avatars.githubusercontent.com/u/14101776?s=280&v=4"),
title: "Flutter",
description: "Flutter is awesome!",
),
),
],
),
ExpansionTile(
title: const FitText.title("FitButton"),
children: [
FitButton(
onTap: () {},
child: const FitText.button("Save"),
),
FitButton(
onTap: () {},
color: Theme.of(context).colorScheme.error,
child: const FitText.button("Save"),
),
FitButton(
onTap: () {},
child: const Icon(Icons.save),
),
],
),
const ExpansionTile(
title: FitText.title("FitTextInput"),
children: [
SizedBox(height: 12),
FitTextInput(
label: "Name",
margin: EdgeInsets.symmetric(horizontal: 12),
),
SizedBox(height: 12),
],
),
const ExpansionTile(
title: FitText.title("FitChips"),
children: [
FitChip(text: "Chip"),
FitRadioChips(
title: "Options",
options: [
"Chip 1",
"Chip 2",
"Chip 3",
"Chip 4",
"Chip 5",
],
),
],
),
const ExpansionTile(
title: FitText.title("FitRadioCards"),
children: [
FitRadioCards(
title: FitText.title("Options"),
options: [
("Option 1", "Lorem Ipsum"),
("Option 2", "Lorem Ipsum"),
("Option 3", "Lorem Ipsum"),
("Option 4", "Lorem Ipsum"),
],
),
],
),
ExpansionTile(
title: const FitText.title("FitSwipeable"),
children: [
FitSwipeable(
options: SwipeOption.add(
onSwiped: () {
context.showSnackbar("Swiped!");
},
background: Container(
color: Theme.of(context).colorScheme.primary,
child: Icon(Icons.add,
color: Theme.of(context)
.colorScheme
.onPrimary),
)),
child: const FitText.body("Swipe me"),
),
FitSwipeable(
options: SwipeOption.delete(
onSwiped: () {
context.showSnackbar("Deleted :(");
},
background: Container(
color: Theme.of(context).colorScheme.error,
child: Icon(Icons.delete,
color: Theme.of(context)
.colorScheme
.onError),
)),
child: const FitText.body("Delete me"),
),
],
),
ExpansionTile(
title: const FitText.title("FitSettings"),
children: [
FitButton(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const ExampleSettings()));
},
child: const FitText.button("Go to settings"),
),
],
),
ExpansionTile(
title: const FitText.title("FitForm"),
children: [
FitButton(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const ExampleForm()));
},
child: const FitText.button("Go to form"),
),
],
),
ExpansionTile(
title: const FitText.title("FitMenu"),
children: [
FitButton(
onTap: () {
showFitMenu(
context,
FitMenu(
mainIcon: Icons.menu,
title: "Fit Menu",
subTitle: "Looks nice doesn't it ?",
menuItems: [
FitMenuItem(
icon: Icons.abc,
title: "Item 1",
onTap: (context, item) {
context.showSnackbar(
"Hello from item 1 !");
}),
FitMenuItem(
icon: Icons.home,
title: "Item 2",
onTap: (context, item) {
context.showSnackbar(
"Hello from item 2 !");
}),
FitMenuItem(
icon: Icons.book,
title: "Item 3",
onTap: (context, item) {
context.showSnackbar(
"Hello from item 3 !");
}),
],
),
);
},
child: const FitText.button("Open menu"),
),
],
),
const ExpansionTile(
title: FitText.title("FitSort"),
children: [
FitSortExample(),
],
),
const ExpansionTile(
title: FitText.title("FitRuleValidator"),
children: [
FitRuleValidator(data: ExampleClass("")),
],
),
ExpansionTile(
title: const FitText.title("FitDialog"),
children: [
FitButton(
onTap: () {
FitDialog(
onConfirm: () => Navigator.of(context).pop(),
child: const Column(
children: [
FitText("Welcome to a FitDialog!")
],
),
).show(context);
},
child: const FitText.button("Show Dialog"),
),
],
)
],
),
),
);
}),
),
);
}),
);
}
}
class FitSortExample extends StatefulWidget {
const FitSortExample({super.key});
[@override](/user/override)
State<FitSortExample> createState() => _FitSortExampleState();
}
class _FitSortExampleState extends State<FitSortExample> {
List<Sortable> data = const [
ExampleClass("a"),
ExampleClass("b"),
ExampleClass("c"),
];
[@override](/user/override)
Widget build(BuildContext context) {
return Column(
children: [
FitSort(
data: data,
availableAlgorithms: [AToZSort(), ZToASort()],
onSortChanged: (newData, sort) {
setState(() {
data = newData;
});
},
),
for (final d in data)
ListTile(
title: FitText.body(d.getComparator().toString()),
),
],
);
}
}
class ExampleClass with RuleValidator implements Sortable {
final String data;
const ExampleClass(this.data);
[@override](/user/override)
Object getComparator() => data;
[@override](/user/override)
Map<String, bool> validate() => {
"Completed Step 1": true,
"Completed Step 2": false,
"Completed Step 3": false,
};
}
class ExampleForm extends StatefulWidget {
const ExampleForm({super.key});
[@override](/user/override)
State<ExampleForm> createState() => _ExampleFormState();
}
class _ExampleFormState extends State<ExampleForm> {
[@override](/user/override)
Widget build(BuildContext context) {
return FitForm(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const FitText("Example Form"),
),
onEnd: () {
Navigator.of(context).pop();
},
pages: const [
FitText.headline("Page 1"),
FitText.headline("Page 2"),
FitText.headline("Page 3"),
],
);
}
}
class ExampleSettings extends StatelessWidget {
const ExampleSettings({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return FitPage(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const FitText("Example Settings"),
),
onRefresh: () async {
context.showSnackbar("Refreshing...");
},
scrollPhysics: const NeverScrollableScrollPhysics(),
children: const [
SettingSection(
title: "Section #1",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingsCruncher(
crunchText: "Info",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
],
),
],
),
SettingSection(
title: "Section #2",
children: [
FitSettingsCruncher(
crunchText: "Info",
children: [
FitSettingsCruncher(
crunchText: "Sub info",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(
title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
],
),
],
),
SettingSection(
title: "Section #1",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingsCruncher(
crunchText: "Info",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
],
),
],
),
SettingSection(
title: "Section #1",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingsCruncher(
crunchText: "Info",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
],
),
],
),
SettingSection(
title: "Section #1",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingsCruncher(
crunchText: "Info",
children: [
FitSettingItem(title: "Name", subtitle: "John Doe"),
FitSettingItem(title: "Address", subtitle: "Place 123 drive"),
FitSettingItem(title: "Name", subtitle: "John Doe"),
],
),
],
),
],
),
],
);
}
}
class LoadingHandlerExample extends StatefulWidget {
const LoadingHandlerExample({super.key});
[@override](/user/override)
State<LoadingHandlerExample> createState() => _LoadingHandlerExampleState();
}
class _LoadingHandlerExampleState extends State<LoadingHandlerExample> {
bool loading = false;
[@override](/user/override)
Widget build(BuildContext context) {
return FitLoadingHandler(
loading: loading,
child: FloatingActionButton.small(
onPressed: () => setState(() {
loading = true;
}),
child: const Icon(Icons.start),
));
}
}
更多关于Flutter界面适配与布局辅助插件flutter_fit_utils_ui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter界面适配与布局辅助插件flutter_fit_utils_ui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter界面适配与布局辅助插件flutter_fit_utils_ui
的使用,以下是一个简单的代码案例,展示了如何集成和使用该插件来优化你的Flutter应用界面适配。
首先,你需要在你的pubspec.yaml
文件中添加对flutter_fit_utils_ui
的依赖:
dependencies:
flutter:
sdk: flutter
flutter_fit_utils_ui: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来获取依赖。
接下来,在你的Flutter项目中,你可以使用flutter_fit_utils_ui
提供的工具类来辅助布局。假设我们要创建一个适配不同屏幕尺寸的简单页面,这里是如何使用flutter_fit_utils_ui
的一个示例:
import 'package:flutter/material.dart';
import 'package:flutter_fit_utils_ui/flutter_fit_utils_ui.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Fit Utils UI Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Fit Utils UI Demo'),
),
body: Center(
child: FitUtilsDemo(),
),
),
);
}
}
class FitUtilsDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 使用FitUtils提供的函数来计算适配屏幕尺寸的宽度和高度
double screenWidth = FitUtils.screenWidth(context);
double screenHeight = FitUtils.screenHeight(context);
double dp32 = FitUtils.dpToPx(context, 32); // 将dp转换为px
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 创建一个宽度为屏幕宽度80%的容器
Container(
width: screenWidth * 0.8,
height: dp32 * 2, // 高度为64dp(32dp * 2)
color: Colors.blue,
child: Center(
child: Text(
'宽度为屏幕宽度的80%',
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(height: dp32), // 垂直间距32dp
// 创建一个高度为屏幕高度40%的容器
Container(
width: dp32 * 4, // 宽度为128dp(32dp * 4)
height: screenHeight * 0.4,
color: Colors.green,
child: Center(
child: Text(
'高度为屏幕高度的40%',
style: TextStyle(color: Colors.white),
),
),
),
],
);
}
}
在这个示例中,我们使用了Flutter Fit Utils UI
插件提供的FitUtils
类来:
- 获取屏幕的宽度和高度。
- 将dp(密度无关像素)转换为px(像素),以便在不同的屏幕上保持一致的视觉大小。
通过这种方式,你可以确保你的布局在不同屏幕尺寸和分辨率的设备上都能很好地适配。
请注意,flutter_fit_utils_ui
插件的具体API和功能可能会随着版本的更新而变化,因此请参考最新的官方文档或插件的GitHub仓库以获取最准确的信息。