首页 > 技术文章 > 【Flutter学习】Flutter工程目录介绍、资源管理、不同分辨率图片、添加依赖

gregpeng 2019-05-27 23:33 原文

项目结构

- projectName
    -android //android的工程文件
    -build //项目的构建输出文件
    -ios //项目的ios工程文件
    -lib //项目中的dart文件
        -src //包含其他的源文件
        -main.dart //自动生成的项目入口文件
    -test //测试相关的文件
    -assets
        -images//建议存放图片
            -2.0x 
            -3.0x
            xxxxx  //图片可以直接放到images
        -fonts//建议存放字体
    -pubspec.yaml //项目依赖配置文件

Flutter资源(assets)介绍

Flutter应用程序可以包含代码和 assets(有时称为资源)。asset是打包到程序安装包中的,可在运行时访问。常见类型的asset包括静态数据(例如JSON文件),配置文件,图标和图片(JPEG,WebP,GIF,动画WebP / GIF,PNG,BMP和WBMP)

指定Assets

资源需要在 pubspec.yaml中配置,配置方法:

flutter:
  assets:
    - assets/my_icon.png
    - assets/background.png

如果使用了未声明的资源,会报错:

资源的实际路径可以是任意的。

Asset 变体(variant)

  1. 变体就是指在构建时,根据不同的场景,选择适应该场景的资源。可以类比Android多图片资源的适配:自动选择加载xxh或者xh下的图片。

  2. 在根据pubspec.yaml构建资源时,会在相邻目录中找到相同名称的任何文件,这些文件会一起打入包中。

    应用程序中有如下文件:
        assets/image/a.png
        assets/image/2x/a.png
        assets/image/3x/a.png
    
    pubspec.yaml 中配置:
        flutter:
            assets:
                - assets/calendar.png
    
    那么,这三种a.png 都会打入asset bundle中。后面2个被认为是变体。
    

加载资源

  1. 通过rootBundle对象来加载(每个Flutter应用都有一个rootBundle对象,可以访问主asset bundle) . 如果你所在的业务场景下,拿不到context(不在widget中),那就使用这个吧,否则使用下面的方式。

    import 'package:flutter/services.dart';
    
    
    Widget _createBody() {
        return new FutureBuilder(
        future: rootBundle.loadString('assets/a.json'),
        builder: (context,snapshot){
            if(snapshot.hasData) {
            return new Text(snapshot.data.toString());
            }
        },
        );
    
  2. 通过DefaultAssetBundle 来获取当前BuildContext 的 AssetBundle,推荐使用。比方法一要灵活。可以自己制定

    import 'package:flutter/services.dart';
    
    
    Widget _createBody() {
        return new FutureBuilder(
        future: DefaultAssetBundle.of(context).loadString('assets/a.json'),
        builder: (context,snapshot){
            if(snapshot.hasData) {
            return new Text(snapshot.data.toString());
            }
        },
        );
    

    针对这2种方式,写了一个简答的demo:

    //采用rootBundle
    class _MyStatelessWidgetState extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return FutureBuilder(
        future: rootBundle.loadString('assets/a.json'),
        builder: (context, snapshot) {
            if (snapshot.hasData) {
            return new Text(snapshot.data.toString());
            } else {
            return new Container(width:0,height: 0,);
            }
        },
        );
    }
    }
    
    

    a.json的内容:

    运行结果:

    class MyStatefulWidget extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
            return DefaultAssetBundle(
            bundle: new TestAssetBundle(),
            child: new  _MyStatelessWidgetState(),
            );
        }
        }
    
        class TestAssetBundle extends CachingAssetBundle {
        @override
        Future<ByteData> load(String key) async {
            if (key == 'assets/a.json')
            return ByteData.view(Uint8List.fromList(utf8.encode('Hello World!')).buffer);
            return null;
        }
        }
    
        class _MyStatelessWidgetState extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
            return FutureBuilder(
            future: DefaultAssetBundle.of(context).loadString('assets/a.json'),
            builder: (context, snapshot) {
                if (snapshot.hasData) {
                return new Text(snapshot.data.toString());
                } else {
                return new Container(width:0,height: 0,);
                }
            },
            );
        }
        }
    

    运行结果:

图片资源

  1. 推荐的存放目录: assets/images

  2. 图片资源需要声明

    后面会介绍pubspec.yaml的相关知识点

  3. 图片资源的使用

不同分辨率的图片

跟Android的多图片适配相同,将不同分辨率下的图片放到对应的目录即可,如下:

使用:

new Image.asset("assets/images/a.png");

说到分辨率这个,有必要去看下Flutter中屏幕的理解和屏幕适配。这块将写成另外一个文档。

strings资源的管理

参考了github上的一些项目,比较合适的管理方式如下:

新建一个.dart文件,比如uidata.dart:

import 'package:flutter/material.dart';

class UIData {
  //routes  页面路径
  static const String homeRoute = "/home";
  static const String profileOneRoute = "/View Profile";
  static const String profileTwoRoute = "/Profile 2";

  //strings
  static const String appName = "Flutter UIKit";

  //fonts  字体相关
  static const String quickFont = "Quicksand";
  static const String ralewayFont = "Raleway";
  static const String quickBoldFont = "Quicksand_Bold.otf";
  static const String quickNormalFont = "Quicksand_Book.otf";
  static const String quickLightFont = "Quicksand_Light.otf";

  //images
  static const String imageDir = "assets/images";
  static const String pkImage = "$imageDir/pk.jpg";

  //login  比如登录页面用到的文本
  static const String enter_code_label = "Phone Number";
  static const String enter_code_hint = "10 Digit Phone Number";

  //gneric 通用的文本
  static const String error = "Error";
  static const String success = "Success";

  static const MaterialColor ui_kit_color = Colors.grey;

//colors
  static List<Color> kitGradients = [
    // new Color.fromRGBO(103, 218, 255, 1.0),
    // new Color.fromRGBO(3, 169, 244, 1.0),
    // new Color.fromRGBO(0, 122, 193, 1.0),
    Colors.blueGrey.shade800,
    Colors.black87,
  ];
  static List<Color> kitGradients2 = [
    Colors.cyan.shade600,
    Colors.blue.shade900
  ];

  //randomcolor
  static final Random _random = new Random();

  /// Returns a random color.
  static Color next() {
    return new Color(0xFF000000 + _random.nextInt(0x00FFFFFF));
  }
}

国际化

TODO gang 待完善
https://flutterchina.club/tutorials/internationalization/

添加依赖

在pubspec.yaml 中添加依赖

注意,只有在添加平台所需相关依赖时,才需要去Android 工程中的gradle中添加依赖。

查找 Flutter插件的网站: https://pub.dev/flutter/packages

推荐阅读