Flutter辅助工具插件helpers的使用
Flutter辅助工具插件helpers的使用
My other APIs
- Scroll Navigation
- Video Viewer
- Video Editor
Features
- 更好的代码可读性。
- 更直观的语句。
- 声明更快。
- 缩短冗长的语句。
Table of Contents
- BuildContext扩展 FAVORITE Plus
- 控制台彩色日志 FAVORITE
- 构建助手
- 杂项助手
- Misc类 FAVORITE
- SystemOverlay类
- SystemOrientation类
- 尺寸助手
- Margin类 FAVORITE
- EdgeRadius类
- 文本助手
- TextDesigned组件
- 主题化的文本组件 FAVORITE
- 过渡助手
- 小部件助手
预览
颜色日志示例
小部件示例
文档
BuildContext扩展
它简化了Theme.of(context)
,MediaQuery.of(context)
和Navigator
的调用。
[@override](/user/override)
Widget build(BuildContext context) {
final BuildColor color = context.color; //DOES THIS: BuildColor(context)
final BuildMedia media = context.media; //DOES THIS: BuildMedia(context)
return Container(
color: color.primary, //DOES THIS: Theme.of(context).primaryColor
width: media.width / 2, //DOES THIS: MediaQuery.of(context).size.width / 2
height: media.height / 2 //DOES THIS: MediaQuery.of(context).size.height / 2
);
}
context.theme //DOES THIS: Theme.of(context)
context.textTheme //DOES THIS: Theme.of(context).textTheme
context.goBack(); //DOES THIS: Navigator.pop(context);
context.to(page); //DOES THIS: Navigator.push(context, MaterialPageRoute(builder: (_) => page));
... //+5 Navigator Locations
控制台彩色日志
它是对控制台日志的个性化。
printPink("I'm an error 凸-_-凸", true);
printYellow("I'm an alert (¯―¯٥)");
printCyan("I'm an info (✿◠‿◠)");
printColor(
"I'm a weird boy ¯\\(°_o)/¯",
PrintColorStyle(
prefix: "Hola baby!",
foreground: Colors.green,
background: Colors.black,
underline: true,
bold: true,
italic: true,
),
);
printColor(
"Controller disposed!",
PrintColorStyle(
bold: true,
prefix: "HELPERS",
foreground: Colors.orangeAccent,
),
);
杂项助手
Misc类
它简化了许多指令。
double milliseconds = 200;
// 回调
Misc.onLayoutRendered(() {}); //Helper
WidgetsBinding.instance.addPostFrameCallback((_) {});
// 定时器-异步
Misc.delayed(milliseconds, () {}); //Helper
Future.delayed(Duration(milliseconds: milliseconds), () {});
Misc.timer(milliseconds, () {}); //Helper
Timer(Duration(milliseconds: milliseconds), () {});
Misc.periodic(milliseconds, () {}); //Helper
Timer.periodic(Duration(milliseconds: milliseconds), () {});
await Misc.wait(milliseconds); //Helper
await Future.delayed(Duration(milliseconds: milliseconds), () {});
// 文本
Text(Misc.loremIpsum());
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
Text(Misc.extendedLoremIpsum());
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.");
// 系统(注意:需要导入flutter services)
Misc.setSystemOverlayStyle(...); //Helper
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(...));
Misc.setSystemOverlay(SystemOverlay.portraitUp); //Helper
SystemChrome.setSystemUIOverlay([SystemUiOverlay.portraitUp]);
Misc.setSystemOrientation(SystemOrientation.values); //Helper
SystemChrome.setPreferredOrientations(DeviceOrientation.values)
SystemOverlay类
这是对List type: SystemUiOverlay
语句的简化。它用于Misc.setSystemOverlayStyle()
语句。
改进: 使用SystemOverlay将不需要导入SystemChrome, DeviceOrientation
来自flutter services。
SystemOverlay.values; //Helper
SystemUiOverlay.values
SystemOverlay.top; //Helper
[SystemUiOverlay.top]
SystemOverlay.bottom; //Helper
[SystemUiOverlay.bottom]
SystemOrientation类
这是对List type: DeviceOrientation
语句的简化。它用于Misc.setSystemOrientation()
语句。
改进: 使用SystemOrientation将不需要导入SystemChrome, DeviceOrientation
来自flutter services。
// 指令
SystemOrientation.values; //Helper
DeviceOrientation.values;
SystemOrientation.portraitUp; //Helper
[DeviceOrientation.portraitUp];
SystemOrientation.portraitDown; //Helper
[DeviceOrientation.portraitDown];
SystemOrientation.landscapeLeft; //Helper
[DeviceOrientation.landscapeLeft];
SystemOrientation.landscapeRight; //Helper
[DeviceOrientation.landscapeRight]
构建助手
BuildMedia类
它是对MediaQuery.of(context)
语句的简化。
final BuildMedia media = BuildMedia(context);
final MediaQueryData query = MediaQuery.of(context);
media.width; //Helper
//query.size.width;
media.height; //Helper
//query.size.height;
media.padding; //Helper
//query.padding;
media.size; //Helper
//query.size;
... //+10 MEDIAQUERIES
BuildColor类
它是对Theme.of(context)
语句的简化。
final BuildColor color = BuildColor(context);
final ThemeData theme = Theme.of(context);
color.primary; //Helper
//theme.primaryColor;
color.primaryLight; //Helper
//theme.primaryColorLight;
color.accent; //Helper
//theme.accentColor;
color.disabled; //Helper
//theme.disabledColor;
color.scaffold; //Helper
//theme.scaffoldBackgroundColor;
... //+20 COLORS
尺寸助手
Margin类
它是对EdgeInsets
语句的简化。
double amount = 2.0;
Margin.zero; //Helper
//EdgeInsets.zero;
Margin.all(amount); //Helper
//EdgeInsets.all(amount);
// 对称
Margin.vertical(amount); //Helper
//EdgeInsets.symmetric(vertical: amount);
Margin.horizontal(amount); //Helper
//EdgeInsets.symmetric(horizontal: amount);
Margin.symmetric(...); //Helper
//EdgeInsets.symmetric(...);
// 只有
Margin.top(amount); //Helper
//EdgeInsets.only(top: amount);
Margin.bottom(amount); //Helper
//EdgeInsets.only(bottom: amount);
Margin.left(amount); //Helper
//EdgeInsets.only(left: amount);
Margin.right(amount); //Helper
//EdgeInsets.only(right: amount);
Margin.only(...); //Helper
//EdgeInsets.only(...);
EdgeRadius类
它是对BorderRadius
语句的简化。
double amount = 2.0;
EdgeRadius.zero; //Helper
//BorderRadius.zero;
EdgeRadius.all(amount); //Helper
//BorderRadius.all(Radius.circular(amount));
// 对称
EdgeRadius.vertical(top: amount, bottom: amount); //Helper
//BorderRadius.vertical(
// top: Radius.circular(top),
// bottom: Radius.circular(bottom));
EdgeRadius.horizontal(left: amount, right: amount); //Helper
//BorderRadius.horizontal(
// left: Radius.circular(left),
// right: Radius.circular(right));
// 只有
EdgeRadius.only( //Helper
topLeft: amount,
topRight: amount,
bottomLeft: amount,
bottomRight: amount);
//BorderRadius.only(
// topLeft: Radius.circular(topLeft),
// topRight: Radius.circular(topRight),
// bottomLeft: Radius.circular(bottomLeft),
// bottomRight: Radius.circular(bottomRight));
文本助手
TextDesigned组件
它是Text Widget
的简化。
//HELPER
TextDesigned(
"Hello",
size: 20,
bold: true,
underline: true,
color: Colors.white,
);
/*
Text(
"Hello",
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline,
),
);*/
主题化的文本组件
带有TextTheme样式的文本组件。
// HEADLINES
Headline1("Hi");
//Text("Hi", style: Misc.textTheme(context).headline1);
Headline2("Hi");
//Text("Hi", style: Misc.textTheme(context).headline2);
Headline3("Hi");
//Text("Hi", style: Misc.textTheme(context).headline3);
Headline4("Hi");
//Text("Hi", style: Misc.textTheme(context).headline4);
Headline5("Hi");
//Text("Hi", style: Misc.textTheme(context).headline5);
Headline6("Hi");
//Text("Hi", style: Misc.textTheme(context).headline6);
// SUBTITLES
Subtitle1("Hi");
//Text("Hi", style: Misc.textTheme(context).subtitle1);
Subtitle2("Hi");
//Text("Hi", style: Misc.textTheme(context).subtitle2);
// BODYTEXTS
BodyText1("Hi");
//Text("Hi", style: Misc.textTheme(context).bodytext1);
BodyText2("Hi");
//Text("Hi", style: Misc.textTheme(context).bodytext2);
// OTHER
Overline//Text("Hi");
//Text("Hi", style: Misc.textTheme(context).overline);
Caption//Text("Hi");
//Text("Hi", style: Misc.textTheme(context).caption);
Button//Text("Hi");
//Text("Hi", style: Misc.textTheme(context).button);
小部件助手
SlidingBottomSheet组件
创建一个类似AlertDialog的SlidingBottomSheet。
//EXAMPLE
conxtext.navigator.pushNoTransition(
SlidingBottomSheet(builder: (_, __) => SlidingBottomSheetContainer(height: 600)),
);
SlidingBottomSheetContainer组件
用于向SlidingBottomSheetPage
[builder]输入内容。
//WIDGET RETURN THAT
return ClipRRect(
borderRadius: borderRadius,
child: Container(
height: height,
width: double.infinity,
child: child,
padding: padding,
decoration: BoxDecoration(boxShadow: boxShadow, color: color),
),
);
RemoveScrollGlow组件
消除PageView,ScrollView,ListView等达到限制时的溅射效果或发光效果。
//WIDGET RETURN THAT
return NotificationListener<OverscrollIndicatorNotification>(
onNotification: (OverscrollIndicatorNotification overscroll) {
overscroll.disallowGlow();
return;
},
child: PageView(...),
);
DismissKeyboard组件
点击某个小部件会将其应用焦点并隐藏键盘。
//WIDGET RETURN THAT
return GestureDetector(
onTap: () {
FocusScopeNode focus = FocusScope.of(context);
if (!focus.hasPrimaryFocus) focus.requestFocus(FocusNode());
},
child: child,
);
SizeBuilder组件
它的工作方式类似于LayoutBuilder,但只返回maxWidth
和maxHeight
。
//EXAMPLE
SizeBuilder(builder: (width, height) {
return Container(
width: width,
height: height,
color: Colors.red,
);
});
/*WIDGET RETURN THAT
return LayoutBuilder(builder: (context, constraints) {
return Container(
width: constraints.maxWidth,
height: constraints.maxHeight,
color: Colors.red,
);
});*/
ExpandedSpacer组件
它在[Row]或[Column]中用作间隔。
//EXAMPLE
Column(children: [
Expanded(child: Icon(Icons.chevron_left)),
ExpandedSpacer(),
ExpandedSpacer(),
Expanded(child: Icon(Icons.chevron_right)),
])
//WIDGET RETURN THAT
//return Expanded(child: SizedBox());
ExpandedAlign组件
通常在[Row]中用于图标或文本。
//EXAMPLE
Row(children: [
ExpandedTap(
onTap: () => print("CANCEL"),
child: Center(
child: TextDesigned(
"CANCEL",
color: Colors.white,
bold: true,
),
),
),
ExpandedTap(
onTap: () => print("OK"),
child: Center(
child: TextDesigned(
"OK",
color: Colors.white,
bold: true,
),
),
),
])
/*WIDGET RETURN THAT
return Expanded(
child: GestureDetector(
onTap: onTap,
child: child,
),
);*/
ExpandedAlign组件
它是[Align]包裹在一个[Expanded]内。
//EXAMPLE
Row(children: [
ExpandedAlign(
alignment: Alignment.centerLeft,
child: TextDesigned(
"CANCEL",
color: Colors.white,
bold: true,
),
),
ExpandedAlign(
alignment: Alignment.centerRight,
child: TextDesigned(
"CANCEL",
color: Colors.white,
bold: true,
),
),
])
/*WIDGET RETURN THAT
return Expanded(
child: Align(
alignment: alignment,
child: child,
),
);*/
SplashTap组件
//WIDGET RETURN THAT
return Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(color: color, shape: shape),
child: InkWell(
child: child,
onTap: onTap,
customBorder: shape == BoxShape.circle ? CircleBorder() : null,
),
),
);
SplashButton组件
//WIDGET RETURN THAT
return DecoratedBox(
decoration: BoxDecoration(
color: Colors.transparent,
shape: shape,
borderRadius: shape != BoxShape.circle ? borderRadius : null,
boxShadow: boxShadow,
),
child: ClipRRect(
borderRadius: borderRadius,
child: SplashTap(
onTap: onTap,
color: color,
shape: shape,
child: Padding(
padding: padding,
child: child,
),
),
),
);
TileDesinged组件
//WIDGET RETURN THAT
return ClipRRect(
borderRadius: borderRadius,
child: SplashTap(
onTap: onTap,
color: background,
child: Container(
padding: padding,
child: Row(children: [
if (prefix != null) prefix,
if (child != null) child,
if (suffix != null) suffix
]),
),
),
);
SafeAreaColor组件
用于创建自己的AppBar。
//EXAMPLE
Column(children: [
SafeAreaColor(
color: Colors.white,
height: 60,
child: Center(TextDesigned("APP BAR", bold: true)),
),
ExpandedSpacer(),
Container(
height: 60,
color: Colors.white,
width: double.infinity,
child: Center(TextDesigned("BOTTOM NAV", bold: true)),
),
])
/*WIDGET RETURN THAT
return Container(
color: color,
width: width,
child: SafeArea(
child: Container(
height: height,
child: child,
),
),
);*/
AnimatedInteractiveViewer组件
它是一个具有增强双击缩放功能的InteractiveViewer。
//EXAMPLE
AnimatedInteractiveViewer(
child: Image.network(
"https://avatars0.githubusercontent.com/u/65832922?s=460&u=67f908b168ae2934f9e832af2180825c6b2f0e37&v=4"),
),
过渡助手
BooleanTween组件
它是一个AnimatedBuilder。如果为TRUE
,则执行Tween从begin到end (controller.forward())
,如果为FALSE
,则执行Tween从end到begin (controller.reverse())
。
它是所有过渡的核心。
//EXAMPLE
bool animate = true;
BooleanTween<Color>(
animate: animate,
tween: ColorTween(begin: Colors.blue, end: Colors.red),
builder: (_, color, __) => Container(color: color),
);
OpacityTransition组件
通过布尔变量,使用淡入淡出过渡显示或隐藏一个Widget。
//EXAMPLE
bool visible = true;
OpacityTransition(
visible: visible,
child: Container(),
);
SwipeTransition组件
通过布尔变量,使用滑动过渡显示或隐藏一个Widget。
//EXAMPLE
bool visible = true;
SwipeTransition(
visible: visible,
direction: SwipeDirection.fromTop,
child: Center(child: TextDesigned("Swipe Transition", bold: true)),
),
TurnTransition组件
通过布尔变量旋转一个Widget。
//EXAMPLE
bool turn = true;
TurnTransition(
turn: turn,
child: Icon(Icons.chevron_left),
);
示例代码
import 'package:flutter/material.dart';
import 'package:helpers/helpers.dart';
void main() => runApp(App());
class App extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
Misc.setSystemOrientation(SystemOrientation.portraitUp);
Misc.setSystemOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
);
return MaterialApp(
home: HomePage(),
theme: ThemeData(
primaryColor: const Color(0xFF37393d),
scaffoldBackgroundColor: Colors.grey[100],
textTheme: const TextTheme(
bodyText1: TextStyle(color: Colors.white),
headline4: TextStyle(
color: Colors.black,
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
),
title: 'HELPERS EXAMPLE',
debugShowCheckedModeBanner: false,
);
}
}
class HomePage extends StatefulWidget {
[@override](/user/override)
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool visible = false;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => visible = !visible),
child: TurnTransition(
turn: visible, child: const Icon(Icons.chevron_left)),
),
body: Column(children: [
SafeAreaColor(
height: 60,
child: Center(
child: BooleanTween<double>(
animate: visible,
tween: Tween<double>(begin: 16, end: 20),
builder: (_, value, __) {
return BodyText1(
"HELPERS EXAMPLE",
style: TextStyle(fontSize: value),
);
},
),
),
),
Expanded(
child: SwipeTransition(
visible: visible,
child: const Center(child: BodyText1("Swipe Transition")),
),
),
Expanded(
child: OpacityTransition(
visible: visible,
child: Center(
child: AnimatedInteractiveViewer(
child: Image.network(
"https://avatars0.githubusercontent.com/u/65832922?s=460&u=67f908b168ae2934f9e832af2180825c6b2f0e37&v=4"),
),
),
),
),
Expanded(
child: SwipeTransition(
visible: visible,
axisAlignment: 1.0,
child: Center(child: BodyText1("Swipe Transition")),
),
),
SplashButton(
onTap: () {
context.navigator.pushNoTransition(
SlidingBottomSheet(
backgroundBlur: 4.4,
builder: (newContext, __) => SlidingBottomSheetContainer(
height: 600,
padding: Margin.all(100),
child: Column(children: [
SplashTap(
onTap: () {
context.navigator.pushNoTransition(Center(
child: Headline4("GG"),
));
},
child: Text("Using BuildContext"),
),
]),
),
),
);
},
child: BodyText1("Open Sliding Panel"),
),
SizedBox(height: 20),
SplashButton(
onTap: () {
printPink("I'm an error 凸-_-凸", bold: true);
printYellow("I'm an alert (¯―¯٥)");
printCyan("I'm an info (✿◠‿◠)");
printColor(
"I'm a weird boy ¯\\(°_o)/¯",
PrintColorStyle(
prefix: "Hola baby!",
foreground: Colors.green,
background: Colors.black,
underline: true,
bold: true,
italic: true,
),
);
printColor(
"Controller disposed!",
PrintColorStyle(
prefix: "HELPERS",
foreground: Colors.orangeAccent,
bold: true,
),
);
},
child: BodyText1("Test console color text"),
),
SizedBox(height: 60),
]),
);
}
}
更多关于Flutter辅助工具插件helpers的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter辅助工具插件helpers的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter开发中,辅助工具插件(helpers)可以极大地提高开发效率和代码质量。这些插件通常封装了一些常用的功能,如网络请求、数据解析、UI组件的复用等。虽然Flutter生态系统中有许多第三方辅助工具插件,但这里我们将通过一个自定义的helper示例来展示如何使用这些工具插件。
假设我们需要创建一个简单的网络请求helper,这个helper将封装HTTP请求的逻辑,使得在应用的各个部分发起网络请求时更加方便。
1. 添加依赖
首先,确保你的pubspec.yaml
文件中添加了http
依赖,这是Flutter中常用的一个HTTP客户端库。
dependencies:
flutter:
sdk: flutter
http: ^0.13.3 # 请根据需要调整版本号
2. 创建网络请求Helper
接下来,创建一个名为network_helper.dart
的文件,并在其中定义我们的网络请求helper。
import 'dart:convert';
import 'package:http/http.dart' as http;
class NetworkHelper {
final String baseUrl = 'https://api.example.com'; // 替换为你的API基础URL
// 发起GET请求
Future<Map<String, dynamic>> get(String endpoint, {Map<String, String>? params}) async {
String url = '$baseUrl$endpoint';
if (params != null) {
url += '?${Uri.encodeQueryComponents(params)}';
}
try {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load data: ${response.statusCode}');
}
} catch (e) {
throw Exception(e.toString());
}
}
// 发起POST请求
Future<Map<String, dynamic>> post(String endpoint, Map<String, dynamic> body) async {
String url = '$baseUrl$endpoint';
try {
http.Response response = await http.post(
Uri.parse(url),
body: jsonEncode(body),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200 || response.statusCode == 201) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load data: ${response.statusCode}');
}
} catch (e) {
throw Exception(e.toString());
}
}
}
3. 使用NetworkHelper
现在,我们可以在应用的任何地方使用这个NetworkHelper
来发起网络请求。例如,在一个ViewModel或Service类中:
import 'package:flutter_app/helpers/network_helper.dart';
class UserService {
final NetworkHelper _networkHelper = NetworkHelper();
// 获取用户信息
Future<Map<String, dynamic>> getUserInfo(String userId) async {
try {
Map<String, dynamic> response = await _networkHelper.get('/users/$userId');
return response;
} catch (e) {
// 处理错误,例如显示Snackbar或日志记录
print(e.toString());
throw e;
}
}
// 更新用户信息
Future<Map<String, dynamic>> updateUserInfo(String userId, Map<String, dynamic> data) async {
try {
Map<String, dynamic> response = await _networkHelper.post('/users/$userId', body: data);
return response;
} catch (e) {
// 处理错误
print(e.toString());
throw e;
}
}
}
4. 在UI中使用UserService
最后,在UI组件中使用这个UserService
来获取或更新用户信息。例如,在一个StatefulWidget中:
import 'package:flutter/material.dart';
import 'package:flutter_app/services/user_service.dart';
class UserProfileScreen extends StatefulWidget {
@override
_UserProfileScreenState createState() => _UserProfileScreenState();
}
class _UserProfileScreenState extends State<UserProfileScreen> {
UserService _userService = UserService();
Map<String, dynamic>? _userInfo;
final TextEditingController _nameController = TextEditingController();
@override
void initState() {
super.initState();
_fetchUserInfo();
}
Future<void> _fetchUserInfo() async {
String userId = '123'; // 假设我们有一个用户ID
try {
_userInfo = await _userService.getUserInfo(userId);
_nameController.value = TextEditingValue(text: _userInfo!['name'] ?? '');
} catch (e) {
// 处理错误
}
}
Future<void> _updateUserInfo() async {
String userId = '123'; // 假设我们有一个用户ID
Map<String, dynamic> updatedData = {'name': _nameController.text};
try {
await _userService.updateUserInfo(userId, updatedData);
// 更新成功后,可以显示Snackbar或刷新UI
} catch (e) {
// 处理错误
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User Profile')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _nameController,
decoration: InputDecoration(labelText: 'Name'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _updateUserInfo,
child: Text('Update Info'),
),
if (_userInfo != null)
Text('Email: ${_userInfo!['email']}'),
],
),
),
);
}
}
以上代码展示了如何创建一个简单的网络请求helper,并在Flutter应用中使用它。这种方法可以帮助你封装和复用网络请求逻辑,使代码更加简洁和易于维护。根据你的具体需求,你可以进一步扩展这个helper,例如添加PUT、DELETE等HTTP方法,或者处理认证和错误重试逻辑。