GetX
状态管理
GetX包含很多功能,各种弹出widget、路由管理、国际化、Utils、状态管理等。
基于路由管理
1. 添加到项目中
1.1. 将此添加到pubspec.yaml文件中。
get: 4.1.4
1.2. 在命令行中运行
flutter packages get
1.3. 在MaterialApp前面加上 “Get”,就可以把它变成GetMaterialApp
GetMaterialApp( home: MyHome(),
)
2. 具体的路由使用场景:
2.1 导航到新的页面。
Get.to(NextScreen());
2.2 关闭SnackBars、Dialogs、BottomSheets或任何你通常会用Navigator.pop(context)关闭的东西。
Get.back();
2.3进入下一个页面,但没有返回上一个页面的选项(用于SplashScreens,登录页面等)。
Get.off(NextScreen());
2.4 进入下一个界面并取消之前的所有路由(在购物车、投票和测试中很有用)。
Get.offAll(NextScreen());
2.5 要导航到下一条路由,并在返回后立即接收或更新数据。
var data = await Get.to(Payment());
2.6 在另一个页面上,发送前一个路由的数据。并使用它,例:
Get.back(result: 'success');
if(data == 'success') madeAnything();
2.7 与标准导航的关系 , 只要把 Navigator(大写)改成 navigator(小写),就可以拥有标准导航的所有功能,而不需要使用context // 默认的Flutter导航
Navigator.of(context).push(context,MaterialPageRoute(builder: (BuildContext context) {return HomePage();},),
);
// 使用Flutter语法获得,而不需要context。
navigator.push(MaterialPageRoute(builder: (_) {return HomePage();},),
);
// get语法 (这要好得多)
Get.to(HomePage());
dio:http 请求库
dio
是一个强大的Dart
Http
请求库,支持Restful API、FormData
、拦截器、请求取消、Cookie
管理、文件上传/下载、超时、自定义适配器等…
1. 添加到项目中
1.1. 将此添加到pubspec.yaml文件中。
dio: ^4.0.6
dio_cookie_manager: ^2.0.0
cookie_jar: ^3.0.1
1.2. 在命令行中运行
flutter packages get
2.具体的使用
一个极简的示例:
import 'package:dio/dio.dart';
void getHttp() async {try {var response = await Dio().get('http://www.google.com');print(response);} catch (e) {print(e);}
}
项目中的使用:
config.dart
统一管理请求接口的
url
地址
// api地址前缀static String imApiUrl() {return 'https://xxxxxx.xxxxx.com/api/users';} // 接口列表
class Urls {static var register = "${Config.imApiUrl()}/register";static var login = "${Config.imApiUrl()}/login";static var getCode = "${Config.imApiUrl()}/getCode";static var verifiCode = "${Config.imApiUrl()}/verifiCode";static var setNewPwd = "${Config.imApiUrl()}/setNewPwd";
}
api_resp.dart
对接口返回的数据,进行统一数据类型校验
class ApiResp {int? code;String? msg;dynamic data;ApiResp.fromJson(Map<String, dynamic> map) {code = map["code"];msg = map["msg"];data = map["data"] ?? {};}Map<String, dynamic> toJson() {final data = <String, dynamic>{};data['code'] = code;data['msg'] = msg;data['data'] = data;return data;}
}
api_interceptor.dart
对于请求的拦截
import 'package:dio/dio.dart';
import 'config.dart';
import 'api_resp.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
Dio dio = Dio();
class HttpUtil {HttpUtil._();static void init() {dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {return handler.next(options);}, onResponse: (response, handler) {return handler.next(response);}, onError: (DioError e, handler) {return handler.next(e);}));dio.interceptors.add(CookieManager(CookieJar()));// 配置dio实例dio.options.baseUrl = Config.imApiUrl();dio.options.connectTimeout = 30000;dio.options.receiveTimeout = 30000;}// post 请求static Future<Map<String, dynamic>> post(String path, {dynamic data,Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,ProgressCallback? onSendProgress,ProgressCallback? onReceiveProgress,}) async {try {var result = await dio.post<Map<String, dynamic>>(path,data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onSendProgress: onSendProgress,onReceiveProgress: onReceiveProgress,);print(result);var resp = ApiResp.fromJson(result.data!);// 成功返回if (resp.code == 0) {var response = {"data": resp.data, "code": resp.code, "msg": resp.msg};return response;} else {// 业务报错return Future.error((resp.msg).toString());}} catch (error) {// 网络报错if (error is DioError) {} else {}return Future.error(error);}}// get请求static Future<Map<String, dynamic>> get(String path, {Map<String, dynamic>? queryParameters,Options? options,CancelToken? cancelToken,ProgressCallback? onReceiveProgress,}) async {try {var result = await dio.get<Map<String, dynamic>>(path,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onReceiveProgress: onReceiveProgress,);var resp = ApiResp.fromJson(result.data!);// 成功返回if (resp.code == 0) {var response = {"data": resp.data ?? {},"code": resp.code,"msg": resp.msg};return response;} else {// 业务报错return Future.error(resp);}} catch (error) {// 网络报错if (error is DioError) {} else {}return Future.error(error);}}
}
apis.dart
请求的接口管理
import 'package:cookie_jar/cookie_jar.dart';
import 'config.dart';
import 'api_interceptor.dart';
class Api {static final CookieJar cookieJar = CookieJar();
}
class Apis {
// 注册static Future<dynamic> register({required String account,required String password,required String code,required String mobile,}) async {Map<dynamic, dynamic> response;response = (await HttpUtil.post(Urls.register, data: {"account": account,"password": password,"mobile": mobile,"code": code}));return response;}
// 获取验证码 static Future<dynamic> getCode({required mobile}) async {Map<String, dynamic> response;response =await HttpUtil.get(Urls.getCode, queryParameters: {"mobile": mobile});return response;}// 校对验证码static Future<dynamic> verifiCode({required mobile, required code}) async {Map<String, dynamic> response;response = await HttpUtil.post(Urls.verifiCode,data: {"mobile": mobile, "code": code});return response;}// 设置新密码static Future<dynamic> setNewPwd({required mobile, required password, required code}) async {Map<String, dynamic> response;response = await HttpUtil.post(Urls.setNewPwd,data: {"mobile": mobile, "password": password, "code": code});return response;}
}
国际化
在
flutter
项目中国际化是必不可少的
1. 添加到项目中
1.1. 将此添加到pubspec.yaml文件中。
flutter_localizations:sdk: flutter
intl: ^0.17.0
flutter_intl:enabled: true
1.2. 在命令行中运行
flutter packages get
2. 在项目中使用
在main.dart
中添加国际化
@overrideWidget build(BuildContext context) {return GetMaterialApp( ...// 以下是国际化需要添加的代码localizationsDelegates: const [GlobalMaterialLocalizations.delegate,GlobalWidgetsLocalizations.delegate,GlobalCupertinoLocalizations.delegate,S.delegate], // 中文为首选项,修改后需重启locale: const Locale('zh', 'CN'),supportedLocales: [...S.delegate.supportedLocales], ...);}
下载完成后,会自动生生以下文件夹
generated
是自动生成的dart
代码I10n
是对应的arb
文件目录
编辑对于同一个词汇,在不同环境对应的内容:
English:
{"hello": "hello"
}
中文:
{"hello": "你好"
}
在代码中的使用:
import 'package:flutter/material.dart';
// 引入文件
import 'package:im_flutter_demo/generated/l10n.dart';
class FirstScreen extends StatelessWidget {FirstScreen({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: Text(// 添加文字S.of(context).hello,),),);}
}
WaterMark 水印
水印组件
可以设置行和列的数量、角度以及显示的文字。
import 'package:flutter/material.dart';
class WatermarkWidget extends StatelessWidget {final int rowCount;final int columnCount;final String text;const WatermarkWidget({Key? key,required this.rowCount,required this.columnCount,required this.text,}) : super(key: key);@overrideWidget build(BuildContext context) {return IgnorePointer(child: Container(margin: const EdgeInsets.only(top: 80, bottom: 80),child: Column(children: creatColumnWidgets(),),),);}
// 行List<Widget> creatRowWdiges() {List<Widget> list = [];for (var i = 0; i < rowCount; i++) {final widget = Expanded(child: Center(child: Transform.rotate(angle: 120,child: Text(text,style: const TextStyle(color: Color.fromARGB(35, 0, 0, 0),fontSize: 16,decoration: TextDecoration.none)))));list.add(widget);}return list;}
// 列List<Widget> creatColumnWidgets() {List<Widget> list = [];for (var i = 0; i < columnCount; i++) {final widget = Expanded(child: Row(children: creatRowWdiges(),));list.add(widget);}return list;}
}
如何使用水印
import 'package:flutter/material.dart';
import 'package:im_flutter_demo/src/widgets/water1.dart';
class Index extends StatefulWidget {const Index({Key? key}) : super(key: key);@overrideState<Index> createState() {return TextWaterMarkPainterState();}
}
class TextWaterMarkPainterState extends State<Index> {OverlayEntry? overlayEntry;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('测试水印')),body: Center(child: Column(crossAxisAlignment: CrossAxisAlignment.center,children: [ElevatedButton(child: const Text("添加水印"),onPressed: () {addWaterMarkter(context, "张三 13800138000", 2, 4);},),ElevatedButton(child: const Text("移除水印"),onPressed: () {removeWatermark();},),],),),);}// 添加水印void addWaterMarkter(BuildContext context, String string, int row, int column) async {OverlayState? overlayState = Overlay.of(context);if (overlayEntry == null) {overlayEntry = OverlayEntry(builder: (context) => WatermarkWidget(rowCount: row,columnCount: column,text: string,));overlayState?.insert(overlayEntry!);}}// 移除水印void removeWatermark() async {if (overlayEntry != null) {overlayEntry!.remove();overlayEntry = null;}}
}
添加后的效果:
移动端适配 flutter_screenutil
flutter_screenutil: ^5.5.3+2
如何使用:
定义页面尺寸常量
static const uIW = 375.0;
static const uIH = 812.0;
在main.dart
中添加,使全局生效
@overrideWidget build(BuildContext context) {return ScreenUtilInit(designSize: const Size(Config.uIW, Config.uIH),minTextAdapt: true,splitScreenMode: true,builder: (context, child) {returnMaterialApp(title: '名称',builder: EasyLoading.init(),...)});}
在布局时如何使用:
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class FirstScreen extends StatelessWidget FirstScreen({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Center(child: SizedBox(width: 100.w,height: 100.h,)),);}
}
图片预览
常用于头像预览,图片预览等场景。
photo_view: ^0.13.0
根据使用场景封装组件:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:photo_view/photo_view.dart';
// 单图片预览
class PhotoViewSimpleScreen extends StatelessWidget {const PhotoViewSimpleScreen({Key? key,required this.imageProvider, //图片required this.heroTag, //hero动画tagid , 不设置或null为不启用hero动画this.loadingChild, //加载时的widgetthis.backgroundDecoration = const BoxDecoration(color: Colors.black), //背景修饰this.minScale, //最大缩放倍数this.maxScale, //最小缩放倍数}) : super(key: key);final ImageProvider imageProvider;final LoadingBuilder? loadingChild;final BoxDecoration backgroundDecoration;final dynamic minScale;final dynamic maxScale;final String heroTag;@overrideWidget build(BuildContext context) {return Scaffold(body: Container(constraints: BoxConstraints.expand(height: MediaQuery.of(context).size.height,),child: Stack(children: <Widget>[Positioned(top: 0,left: 0,bottom: 0,right: 0,child: PhotoView(imageProvider: imageProvider,loadingBuilder: loadingChild,backgroundDecoration: backgroundDecoration,minScale: minScale,maxScale: maxScale,heroAttributes: PhotoViewHeroAttributes(tag: heroTag),enableRotation: true, //是否允许旋转),),GestureDetector(onTap: () {// print('context:$context');Get.back();},)],),),);}
}
具体使用:
...
showDialog(barrierColor: Colors.black,context: context,builder: (context) {return const PhotoViewSimpleScreen(imageProvider: NetworkImage('https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e5677df5f1fe4df2b266273c3188ea37~tplv-k3u1fbpfcp-watermark.image?',),heroTag: 'simple');}
)
...
列表展示:
预览效果:
CSS Colors
颜色
CSS Colors package
此包定义
CSS
颜色的颜色常量。这些颜色常量使用dart:ui
中的color
类,这意味着它们对Flutter
应用程序很有用。
1. 在 pubspec.yaml
,添加依赖 css-colors
:
css_colors: ^1.0.0
2. 在命令行中运行
flutter packages get
3. 具体使用
import 'package:css_colors/css_colors.dart';
// 这个就是上面下载的package
import 'package:flutter/material.dart';
void main() {runApp(const APage());
}
class APage extends StatelessWidget {const APage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return const MaterialApp(home: DemoPage(),);}
}
class DemoPage extends StatelessWidget {const DemoPage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: Container(color: CSSColors.orange));}
}
显示页面:
最后
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享