Flutter资源文件加载

413 阅读2分钟

Flutter资源加载

- assets
	- fonts
		iconfont.ttf
	- img
		- 2.0x
		- 3.0x
		wechat.png

图片

所有图片按照倍率的不同,存放在不同的文件夹内,在 pubspec.yaml 中这样引用

flutter:

  # To add assets to your application, add an assets section, like this:
  assets:
     - assets/img/
     - assets/img/2.0x/
     - assets/img/3.0x/

为了方便在代码中引用图片资源,我们生成一个 R.dart 资源文件

class R {
  static final String assetsImgWechat = 'assets/img/wechat';
}

之后在代码里可以直接使用:

Image.asset(R.assetsImgWechat, width: 100.0)

图片处理脚本

// Copyright 2018 DebuggerX <dx8917312@gmail.com>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

var preview_server_port = 2227;

void main() async {
  generatorByAssets();
}

void generatorByAssets() async {
  var directory = new Directory("assets/img");
  var newLines = <String>[];
  var varNames = <String>[];
  var resource = <String>[];
  if (directory.existsSync()) {
    var list = directory.listSync(recursive: false);
    for (var file in list) {
      if (new File(file.path).statSync().type == FileSystemEntityType.file &&
          !file.path.contains('.DS_Store')) {
        if (file.path.contains('@2x')) {
          var newpath = file.path.replaceAll('assets/img', 'assets/img/2.0x');
          newpath = newpath.replaceAll('@2x', '');
          var f = File(file.path);
          f.copySync(newpath);
          file.delete();
          continue;
        }
        if (file.path.contains('@3x')) {
          var newpath = file.path.replaceAll('assets/img', 'assets/img/3.0x');
          newpath = newpath.replaceAll('@3x', '');
          var f = File(file.path);
          f.copySync(newpath);
          file.delete();
          continue;
        }

        var path = file.path.replaceAll('\\', '/');
        var varName = path
            .replaceAll('-', '_')
            .replaceAll('/', '_')
            .replaceAll('.png', '')
            .replaceAll('.jpg', '')
            .replaceAll('.jpeg', '')
            .toLowerCase();
        var pos = 0;
        String char;
        while (true) {
          pos = varName.indexOf('_', pos);
          if (pos == -1) break;
          char = varName.substring(pos + 1, pos + 2);
          varName = varName.replaceFirst('_$char', '_${char.toUpperCase()}');
          pos++;
        }
        varName = varName.replaceAll('_', '');
        resource.add("static final String $varName = '$path';");
        varNames.add("    $varName,");
        newLines.add('    - $path');
      }
    }
  } else {
    throw new FileSystemException('Directory wrong');
  }

  var r = new File('lib/common/r.dart');
  if (r.existsSync()) {
    r.deleteSync();
  }
  r.createSync();
  var content = 'class R {\n';
  for (var line in resource) {
    content = '$content  $line\n';
  }
  content = '$content}';
  // content = '$content\n  static final values = [\n';
  // for (var line in varNames) {
  //   content = '$content$line\n';
  // }
  // content = '$content  ];\n}\n';
  r.writeAsStringSync(content);
}

void generatorByPubspec() async {
  bool working = false;
  var pubSpec = new File('pubspec.yaml');
  var pubLines = pubSpec.readAsLinesSync();
  var newLines = <String>[];
  var varNames = <String>[];
  var resource = <String>[];
  for (var line in pubLines) {
    if (line.contains('begin') &&
        line.contains('#') &&
        line.contains('assets')) {
      working = true;
      newLines.add(line);
    }
    if (line.contains('end') && line.contains('#') && line.contains('assets'))
      working = false;
    if (working) {
      if (line.trim().startsWith('#') && line.trim().endsWith('*')) {
        newLines.add(line);
        var directory =
            new Directory(line.replaceAll('#', '').replaceAll('*', '').trim());
        if (directory.existsSync()) {
          var list = directory.listSync(recursive: true);
          for (var file in list) {
            if (new File(file.path).statSync().type ==
                FileSystemEntityType.file) {
              var path = file.path.replaceAll('\\', '/');
              var varName =
                  path.replaceAll('/', '_').replaceAll('.', '_').toLowerCase();
              var pos = 0;
              String char;
              while (true) {
                pos = varName.indexOf('_', pos);
                if (pos == -1) break;
                char = varName.substring(pos + 1, pos + 2);
                varName =
                    varName.replaceFirst('_$char', '_${char.toUpperCase()}');
                pos++;
              }
              varName = varName.replaceAll('_', '');
              resource
                  .add("/// ![](http://127.0.0.1:$preview_server_port/$path)");
              resource.add("static final String $varName = '$path';");
              varNames.add("    $varName,");
              newLines.add('    - $path');
            }
          }
        } else {
          throw new FileSystemException('Directory wrong');
        }
      }
    } else {
      newLines.add(line);
    }
  }

  var r = new File('lib/r.dart');
  if (r.existsSync()) {
    r.deleteSync();
  }
  r.createSync();
  var content = 'class R {\n';
  for (var line in resource) {
    content = '$content  $line\n';
  }
  content = '$content\n  static final values = [\n';
  print(content);

  for (var line in varNames) {
    content = '$content  $line\n';
  }
  content = '$content  ];\n}\n';
  r.writeAsStringSync(content);

  var spec = '';
  for (var line in newLines) {
    spec = '$spec$line\n';
  }
  pubSpec.writeAsStringSync(spec);

  var ser;
  try {
    ser = await HttpServer.bind('127.0.0.1', preview_server_port);
    print('成功启动图片预览服务器于本机<$preview_server_port>端口');
    ser.listen(
      (req) {
        var index = req.uri.path.lastIndexOf('.');
        var subType = req.uri.path.substring(index + 1);
        print(subType);
        req.response
          ..headers.contentType = new ContentType('image', subType)
          ..add(new File('.${req.uri.path}').readAsBytesSync())
          ..close();
      },
    );
  } catch (e) {
    print('图片预览服务器已启动或端口被占用');
  }
}

Font

  1. 导入字体图标文件;这一步和导入字体文件相同,假设我们的字体图标文件保存在项目根目录下,路径为"fonts/iconfont.ttf":

    fonts:
      - family: myIcon  #指定一个字体名
        fonts:
          - asset: fonts/iconfont.ttf
    
  2. 为了使用方便,我们定义一个MyIcons类,功能和Icons类一样:将字体文件中的所有图标都定义成静态变量:

    class MyIcons{
      // book 图标
      static const IconData book = const IconData(
          0xe614, 
          fontFamily: 'myIcon', 
          matchTextDirection: true
      );
      // 微信图标
      static const IconData wechat = const IconData(
          0xec7d,  
          fontFamily: 'myIcon', 
          matchTextDirection: true
      );
    }
    
  3. 使用

    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Icon(MyIcons.book,color: Colors.purple,),
        Icon(MyIcons.wechat,color: Colors.green,),
      ],
    )