likes
comments
collection
share

【Flutter】之便于提高开发效率的周边库和轮子

作者站长头像
站长
· 阅读数 37

前言

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管理、文件上传/下载、超时、自定义适配器等...

dio文档

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中添加国际化

@override
  Widget 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文件目录

【Flutter】之便于提高开发效率的周边库和轮子

编辑对于同一个词汇,在不同环境对应的内容:

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);
  @override
  Widget 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);

  @override
  Widget 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);

  @override
  State<Index> createState() {
    return TextWaterMarkPainterState();
  }
}

class TextWaterMarkPainterState extends State<Index> {
  OverlayEntry? overlayEntry;

  @override
  Widget 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】之便于提高开发效率的周边库和轮子


移动端适配 flutter_screenutil

 flutter_screenutil: ^5.5.3+2

如何使用:

定义页面尺寸常量

 static const uIW = 375.0;
 static const uIH = 812.0;

main.dart 中添加,使全局生效

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
        designSize: const Size(Config.uIW, Config.uIH),
        minTextAdapt: true,
        splitScreenMode: true,
        builder: (context, child) {
          return  MaterialApp(
            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);
  @override
  Widget 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, //加载时的widget
    this.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;

  @override
  Widget 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();
              },
            )
          ],
        ),
      ),
    );
  }
}

具体使用:

列表展示:

【Flutter】之便于提高开发效率的周边库和轮子

预览效果:

【Flutter】之便于提高开发效率的周边库和轮子


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);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: DemoPage(),
    );
  }
}

class DemoPage extends StatelessWidget {
  const DemoPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: Container(color: CSSColors.orange));
  }
}

显示页面:

【Flutter】之便于提高开发效率的周边库和轮子

转载自:https://juejin.cn/post/7172889862893207582
评论
请登录