Flutter使用flutter_gen管理资源文件

pub地址:

https://pub.dev/packages/flutter_gen

1.添加依赖

在你的pubspec.yaml文件中添加flutter_gen作为开发依赖

Dart 复制代码
dependencies:
  build_runner:
  flutter_gen_runner:

2.配置pubspec.yaml

在pubspec.yaml文件中,配置flutter_gen的参数。指定输出路径和资源路径。

Dart 复制代码
flutter_gen:
  output: lib/gen/ # Optional (default: lib/gen/)
  lineLength: 80   # Optional (default: 80)
  # Optional
  integrations:
    flutter_svg: true   # .svg  Assets.images.icons.paint.svg()
    flare_flutter: true # .flr  Assets.flare.penguin.flare()
    rive: true          # .flr  Assets.rive.vehicles.rive()
    lottie: true        # .json Assets.lottie.hamburgerArrow.lottie()
  colors:
    inputs:
      - assets/colors/colors.xml

flutter:
  uses-material-design: true
  assets:
    - assets/images/tab_home_default.png
    - assets/images/tab_home_selected.png
    - assets/images/tab_category_default.png
    - assets/images/tab_category_selected.png
    - assets/images/tab_mine_default.png
    - assets/images/tab_mine_selected.png
    - assets/images/photo.png
    - assets/images/font.png
    - assets/files/mov_file.mov
    - assets/files/mp3_file.mp3
    - assets/files/mp4_file.mp4
    - assets/files/pdf_file.pdf
    - assets/files/svga_file.svga
    - assets/files/txt_file.txt
    - assets/files/xlsx_file.xlsx
    - assets/files/zip_file.zip

  fonts:
    - family: simkai
      fonts:
        - asset: assets/fonts/simkai.ttf
    - family: SourceHanSerifCNBold
      fonts:
        - asset: assets/fonts/SourceHanSerifCN-Bold.otf
          weight: 700

3.运行生成命令

使用Flutter命令行工具运行pub get来安装新的依赖

Dart 复制代码
$ flutter pub get

使用命令行工具运行命令生成资源文件

Dart 复制代码
$ dart run build_runner build
或
$ flutter packages pub run build_runner build
或
$ flutter packages pub run build_runner build --delete-conflicting-outputs

如果图片资源发生变化,只需更新pubspec.yaml文件并重新运行生成资源文件的命令即可更新资源引用。

4.使用图片和其它资源文件

flutter_gen会在指定的输出目录(例如lib/gen/)中生成一个assets.gen.dart文件,里面包含了所有的资源引用。

使用图片
Dart 复制代码
import 'gen/assets.gen.dart';

Image.asset(
  Assets.images.photo.path, //'assets/images/photo.png',
  width: 50,
  height: 50,
),

Assets.images.font.image(
  width: 100,
  height: 100,
)
使用其它文件
Dart 复制代码
import 'package:flutter/services.dart' show rootBundle;
import 'dart:typed_data';

  var arr = [
    Assets.files.txtFile,
    Assets.files.movFile,
    Assets.files.mp3File,
    Assets.files.mp4File,
    Assets.files.pdfFile,
    Assets.files.svgaFile,
    Assets.files.xlsxFile,
    Assets.files.zipFile
  ];

// 获取文件中的字符串
Future<String> loadAsset(String path) async {
  try {
    var str = await rootBundle.loadString(path);
    return str;
  } catch (e) {
    return "获取失败";
  }
}

// 获取文件二进制数据
Future<ByteData> loadAssetData(String path) async {
  try {
    var data = await rootBundle.load(path);
    return data;
  } catch (e) {
    return ByteData(0);
  }
}

Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      FutureBuilder<String>(
        future: loadAsset(Assets.files.txtFile),
        builder: (BuildContext context,
            AsyncSnapshot<String> snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            return Text(snapshot.data ?? '');
          } else {
            return const CircularProgressIndicator();
          }
        },
      ),

      FutureBuilder<ByteData>(
        future: loadAssetData(Assets.files.mp3File),
        builder: (BuildContext context,
            AsyncSnapshot<ByteData> snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // 这里你可以使用 snapshot.data 来访问文件的二进制数据
            Uint8List data =
                snapshot.data?.buffer.asUint8List() ??
                    Uint8List(0);
            return Container(
              child: Text(data.toString()),
            );
          } else {
            return const CircularProgressIndicator();
          }
        },
      ),
    ],
  ),
资源文件适配

Flutter默认会按照这样的文件夹结构来寻找合适的资源:

  • .../image.png --- 默认图片,适用于1.0x设备像素比的屏幕。

  • .../2.0x/image.png --- 适用于2.0x设备像素比的屏幕。

  • .../3.0x/image.png --- 适用于3.0x设备像素比的屏幕。

当你在应用中引用图像时,只需引用默认的图片路径(.../image.png),Flutter会自动根据设备的像素密度来加载正确的资源文件。如果你的应用不需要支持多种像素密度的图像,那么你也可以只提供默认的图像资源而不创建这些文件夹。

如果你决定支持不同的像素密度,确保为每个分辨率提供相应的图像资源,并按照上述结构放置它们。这样,Flutter就可以为不同的设备屏幕自动选择最合适的资源。

flutter_gen生成的assets.gen.dart
Dart 复制代码
/// GENERATED CODE - DO NOT MODIFY BY HAND
/// *****************************************************
///  FlutterGen
/// *****************************************************

// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use

import 'package:flutter/widgets.dart';

class $AssetsFilesGen {
  const $AssetsFilesGen();

  /// File path: assets/files/mov_file.mov
  String get movFile => 'assets/files/mov_file.mov';

  /// File path: assets/files/mp3_file.mp3
  String get mp3File => 'assets/files/mp3_file.mp3';

  /// File path: assets/files/mp4_file.mp4
  String get mp4File => 'assets/files/mp4_file.mp4';

  /// File path: assets/files/pdf_file.pdf
  String get pdfFile => 'assets/files/pdf_file.pdf';

  /// File path: assets/files/svga_file.svga
  String get svgaFile => 'assets/files/svga_file.svga';

  /// File path: assets/files/txt_file.txt
  String get txtFile => 'assets/files/txt_file.txt';

  /// File path: assets/files/xlsx_file.xlsx
  String get xlsxFile => 'assets/files/xlsx_file.xlsx';

  /// File path: assets/files/zip_file.zip
  String get zipFile => 'assets/files/zip_file.zip';

  /// List of all assets
  List<String> get values => [
        movFile,
        mp3File,
        mp4File,
        pdfFile,
        svgaFile,
        txtFile,
        xlsxFile,
        zipFile
      ];
}

class $AssetsImagesGen {
  const $AssetsImagesGen();

  /// File path: assets/images/font.png
  AssetGenImage get font => const AssetGenImage('assets/images/font.png');

  /// File path: assets/images/photo.png
  AssetGenImage get photo => const AssetGenImage('assets/images/photo.png');

  /// File path: assets/images/tab_category_default.png
  AssetGenImage get tabCategoryDefault =>
      const AssetGenImage('assets/images/tab_category_default.png');

  /// File path: assets/images/tab_category_selected.png
  AssetGenImage get tabCategorySelected =>
      const AssetGenImage('assets/images/tab_category_selected.png');

  /// File path: assets/images/tab_home_default.png
  AssetGenImage get tabHomeDefault =>
      const AssetGenImage('assets/images/tab_home_default.png');

  /// File path: assets/images/tab_home_selected.png
  AssetGenImage get tabHomeSelected =>
      const AssetGenImage('assets/images/tab_home_selected.png');

  /// File path: assets/images/tab_mine_default.png
  AssetGenImage get tabMineDefault =>
      const AssetGenImage('assets/images/tab_mine_default.png');

  /// File path: assets/images/tab_mine_selected.png
  AssetGenImage get tabMineSelected =>
      const AssetGenImage('assets/images/tab_mine_selected.png');

  /// List of all assets
  List<AssetGenImage> get values => [
        font,
        photo,
        tabCategoryDefault,
        tabCategorySelected,
        tabHomeDefault,
        tabHomeSelected,
        tabMineDefault,
        tabMineSelected
      ];
}

class Assets {
  Assets._();

  static const $AssetsFilesGen files = $AssetsFilesGen();
  static const $AssetsImagesGen images = $AssetsImagesGen();
}

class AssetGenImage {
  const AssetGenImage(this._assetName);

  final String _assetName;

  Image image({
    Key? key,
    AssetBundle? bundle,
    ImageFrameBuilder? frameBuilder,
    ImageErrorWidgetBuilder? errorBuilder,
    String? semanticLabel,
    bool excludeFromSemantics = false,
    double? scale,
    double? width,
    double? height,
    Color? color,
    Animation<double>? opacity,
    BlendMode? colorBlendMode,
    BoxFit? fit,
    AlignmentGeometry alignment = Alignment.center,
    ImageRepeat repeat = ImageRepeat.noRepeat,
    Rect? centerSlice,
    bool matchTextDirection = false,
    bool gaplessPlayback = false,
    bool isAntiAlias = false,
    String? package,
    FilterQuality filterQuality = FilterQuality.low,
    int? cacheWidth,
    int? cacheHeight,
  }) {
    return Image.asset(
      _assetName,
      key: key,
      bundle: bundle,
      frameBuilder: frameBuilder,
      errorBuilder: errorBuilder,
      semanticLabel: semanticLabel,
      excludeFromSemantics: excludeFromSemantics,
      scale: scale,
      width: width,
      height: height,
      color: color,
      opacity: opacity,
      colorBlendMode: colorBlendMode,
      fit: fit,
      alignment: alignment,
      repeat: repeat,
      centerSlice: centerSlice,
      matchTextDirection: matchTextDirection,
      gaplessPlayback: gaplessPlayback,
      isAntiAlias: isAntiAlias,
      package: package,
      filterQuality: filterQuality,
      cacheWidth: cacheWidth,
      cacheHeight: cacheHeight,
    );
  }

  ImageProvider provider({
    AssetBundle? bundle,
    String? package,
  }) {
    return AssetImage(
      _assetName,
      bundle: bundle,
      package: package,
    );
  }

  String get path => _assetName;

  String get keyName => _assetName;
}

5.使用颜色资源文件

flutter_gen会在指定的输出目录(例如lib/gen/)中生成一个colors.gen.dart文件,里面包含了颜色的资源引用。

使用颜色
Dart 复制代码
import 'gen/colors.gen.dart';

child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      const Text(
        "字符串1",
        style: TextStyle(
          color: Colors.red,
        ),
      ),
      const Text(
        "字符串1",
        style: TextStyle(
          color: ColorName.textColor,
        ),
      ),
      Text(
        "字符串3",
        style: TextStyle(
          color: ColorName.themeColor[300],
        ),
      ),
      Text(
        "字符串4",
        style: TextStyle(
          color: ColorName.themeColorAccent[400],
        ),
      ),
    ],
  ),
colors.xml
Dart 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <color name="text_color" type="material">#333333</color>
    <color name="theme_color" type="material material-accent">#333333</color>
</resources>
flutter_gen生成的colors.gen.dart
Dart 复制代码
/// GENERATED CODE - DO NOT MODIFY BY HAND
/// *****************************************************
///  FlutterGen
/// *****************************************************

// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use

import 'package:flutter/painting.dart';
import 'package:flutter/material.dart';

class ColorName {
  ColorName._();

  /// Color: #FF000000
  static const Color black = Color(0xFF000000);

  /// MaterialColor:
  ///   50: #FFE7E7E7
  ///   100: #FFC2C2C2
  ///   200: #FF999999
  ///   300: #FF707070
  ///   400: #FF525252
  ///   500: #FF333333
  ///   600: #FF2E2E2E
  ///   700: #FF272727
  ///   800: #FF202020
  ///   900: #FF141414
  static const MaterialColor textColor = MaterialColor(
    0xFF333333,
    <int, Color>{
      50: Color(0xFFE7E7E7),
      100: Color(0xFFC2C2C2),
      200: Color(0xFF999999),
      300: Color(0xFF707070),
      400: Color(0xFF525252),
      500: Color(0xFF333333),
      600: Color(0xFF2E2E2E),
      700: Color(0xFF272727),
      800: Color(0xFF202020),
      900: Color(0xFF141414),
    },
  );

  /// MaterialColor:
  ///   50: #FFE7E7E7
  ///   100: #FFC2C2C2
  ///   200: #FF999999
  ///   300: #FF707070
  ///   400: #FF525252
  ///   500: #FF333333
  ///   600: #FF2E2E2E
  ///   700: #FF272727
  ///   800: #FF202020
  ///   900: #FF141414
  static const MaterialColor themeColor = MaterialColor(
    0xFF333333,
    <int, Color>{
      50: Color(0xFFE7E7E7),
      100: Color(0xFFC2C2C2),
      200: Color(0xFF999999),
      300: Color(0xFF707070),
      400: Color(0xFF525252),
      500: Color(0xFF333333),
      600: Color(0xFF2E2E2E),
      700: Color(0xFF272727),
      800: Color(0xFF202020),
      900: Color(0xFF141414),
    },
  );

  /// MaterialAccentColor:
  ///   100: #FFE82D2D
  ///   200: #FFC21616
  ///   400: #FFBE0000
  ///   700: #FFAF0000
  static const MaterialAccentColor themeColorAccent = MaterialAccentColor(
    0xFFC21616,
    <int, Color>{
      100: Color(0xFFE82D2D),
      200: Color(0xFFC21616),
      400: Color(0xFFBE0000),
      700: Color(0xFFAF0000),
    },
  );

  /// Color: #FFFFFFFF
  static const Color white = Color(0xFFFFFFFF);
}

6.使用字体资源文件

flutter_gen会在指定的输出目录(例如lib/gen/)中生成一个colors.gen.dart文件,里面包含了颜色的资源引用。

使用字体
Dart 复制代码
import 'gen/fonts.gen.dart';

const Text(
  "字体",
  style: TextStyle(
    fontFamily: FontFamily.simkai,
    fontFamilyFallback: [FontFamily.sourceHanSerifCNBold],
  ),
),

通常,fontFamilyFallback用于指定一系列的备选字体,以确保在主字体不支持某些字符时,文本仍然可以用其他字体显示。如果你确定FontFamily.simkai能够支持你需要显示的所有字符,那么就不需要在fontFamilyFallback中再次指定它。相反,如果你有理由相信FontFamily.simkai可能不包含某些字符,那么应该在fontFamilyFallback中指定一个或多个不同的备选字体。

flutter_gen生成的fonts.gen.dart
Dart 复制代码
/// GENERATED CODE - DO NOT MODIFY BY HAND
/// *****************************************************
///  FlutterGen
/// *****************************************************

// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use

class FontFamily {
  FontFamily._();

  /// Font family: SourceHanSerifCNBold
  static const String sourceHanSerifCNBold = 'SourceHanSerifCNBold';

  /// Font family: simkai
  static const String simkai = 'simkai';
}
相关推荐
程序员老刘2 小时前
一杯奶茶钱,PicGo + 阿里云 OSS 搭建永久稳定的个人图床
flutter·markdown
奋斗的小青年!!5 小时前
OpenHarmony Flutter 拖拽排序组件性能优化与跨平台适配指南
flutter·harmonyos·鸿蒙
小雨下雨的雨6 小时前
Flutter 框架跨平台鸿蒙开发 —— Stack 控件之三维层叠艺术
flutter·华为·harmonyos
行者967 小时前
OpenHarmony平台Flutter手风琴菜单组件的跨平台适配实践
flutter·harmonyos·鸿蒙
小雨下雨的雨9 小时前
Flutter 框架跨平台鸿蒙开发 —— Flex 控件之响应式弹性布局
flutter·ui·华为·harmonyos·鸿蒙系统
cn_mengbei9 小时前
Flutter for OpenHarmony 实战:CheckboxListTile 复选框列表项详解
flutter
cn_mengbei9 小时前
Flutter for OpenHarmony 实战:Switch 开关按钮详解
flutter
奋斗的小青年!!9 小时前
OpenHarmony Flutter实战:打造高性能订单确认流程步骤条
flutter·harmonyos·鸿蒙
Coder_Boy_9 小时前
Flutter基础介绍-跨平台移动应用开发框架
spring boot·flutter
cn_mengbei9 小时前
Flutter for OpenHarmony 实战:Slider 滑块控件详解
flutter