添加图片到Flutter

https://flutter.io/assets-and-images/

介绍:

Flutter app需要有代码与assets,assets是文件,部署在app里面的,在运行时可以访问,通常的assets包含,数据,配置文件,图标,图片.

指定assets

Flutter使用pubspec.yaml文件,定位项目的根,以定位assets.

示例:

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

要包含所有的assets东西,可以简化一下

flutter:
  assets:
    - assets/

只在这个目录里的文件会被包含进来,如果是子目录需要添加引用.

assets 绑定

assets,指定了在Flutter app包含的文件.每一个assets 以路径标识.(相对于pubspec.yaml),顺序不重要.真实目录也不重要.

构建过程,Flutter会把这些打包进assets的bundle,这些可以运行时访问的.

assets 变体

构建过程,支持assets 变体,一个assets 的不同版本会在不同的上下文展示,当一个assets 在yaml里配置了.构建进程会查找邻近目录所有相同名字文件.

如,目录下有以下文件:

 .../pubspec.yaml
  .../graphics/my_icon.png
  .../graphics/background.png
  .../graphics/dark/background.png
  ...etc.

你的文件包含

flutter:
  assets:
    - graphics/background.png

graphics/background.png and graphics/dark/background.png 会同时被引进的.普通的是认为主assets,另一个是变体

也可以在yaml里使用目录来指定

flutter:
  assets:
    - graphics/

这样graphics/my_icon.pnggraphics/background.png and graphics/dark/background.png就全部包含进来了.

Flutter在不同分辨率适配时使用变体.这种机制可以扩展到语言环境等情况.

加载Assets

使用AssetBundle对象来访问assets

两个主要的方法允许你加载字符,文件的assets,loadString()或图片load().需要一个逻辑key,逻辑key在构建时映射到路径上.

加载文本的assets

每一个Flutter app有一个rootBundle对象,可以很容易地访问assets.可以通过全局静态导入的来加载.package:flutter/services.dart.

然而,还是建议使用AssetBundle,传入当前的BuildContext来加载.这种方式,会让父控件,去适配不同的assetbundle,可以本地化.可测试.

通常,使用DefaultAssetBundle.of()直接加载.

在控件上下文外,要处理AssetBundle是不可行的时候,可以使用rootBundle来加载.

import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/config.json');
}

加载图片:

Flutter可以处理不同分辨率的图片.

定义不同分辨率的图片assets

AssetImage知道如何去映射一个请求,以适配当前的分辨率.要处理这种映射,asset需要按特定的目录去组织文件:

 .../image.png
  .../Mx/image.png
  .../Nx/image.png
  ...etc.

这点与Android是类似的.xhdpi/xxhdpi等.

M/N表示分辨率值,换句话说,他们指定了设备的缩放率.

主asset默认是1.0,如my_icon.png:

 .../my_icon.png
  .../2.0x/my_icon.png
  .../3.0x/my_icon.png

像素缩放比是1.8的设备上,2.0x/my_icon.png会被选中,2.7的会对应3.0x的图片.

如果Image的高宽不指定,默认的分辨率会使用缩放来适应.如果高宽未指定,3x与1x的图片都会在1x的高宽上渲染的.

pubspec.yaml里的每一个入口都需要对应真实的文件.否则会有异常.如果主asset入口不映射到一个真实文件,低分辨率的会被使用.

加载图片:

要加载图片,使用AssetImage类.在控件的build方法里

如添加背景图

Widget build(BuildContext context) {
  // ...
  return DecoratedBox(
    decoration: BoxDecoration(
      image: DecorationImage(
        image: AssetImage('graphics/background.png'),
        // ...
      ),
      // ...
    ),
  );
  // ...
}

继承默认的asset bundle会继承分辨率.

添加图片到包依赖:

从依赖包中加载图片,包参数需要提供给AssetImage.假如你的app依赖my_icons包,它的目录是:

.../pubspec.yaml
  .../icons/heart.png
  .../icons/1.5x/heart.png
  .../icons/2.0x/heart.png
  ...etc.

加载时:

AssetImage('icons/heart.png', package: 'my_icons')

该包加载时,也要带包参数

绑定包assets

在yaml里指定的,会自动打包进来的.app使用的都要在yaml里指定.

一个包,也可以选择放在lib目录中,不在yaml里指定.如在fancy_backgrounds 包下的文件:

.../lib/backgrounds/background1.png
  .../lib/backgrounds/background2.png
  .../lib/backgrounds/background3.png

要引用第一张图片,也要指定它:

flutter:
  assets:
    - packages/fancy_backgrounds/backgrounds/background1.png

lib/目录不需要再包含,它是隐式地.

不同平台共享资源:

Flutter的assets可以通过不同平台的AssetManager来管理.

Android

可以使用AssetManager来管理.FlutterView的lookupKeyForAsseton PluginRegistry.Registrar or getLookupKeyForAsset 可以实现查找.PluginRegistry.Registrar在开发插件时,选用.

假设你在yaml里这么写:

flutter:
  assets:
    - icons/heart.png

在你app里的结构:

.../pubspec.yaml
  .../icons/heart.png
  ...etc.

要在java代码里访问icons/heart.png,需要:

AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("icons/heart.png");
AssetFileDescriptor fd = assetManager.openFd(key);

IOS

mainBundle可以访问它.pathForResource:ofType: 类型的key也是通过FlutterViewController的lookupKeyForAsset or lookupKeyForAsset:fromPackage: on FlutterPluginRegistrar or lookupKeyForAsset: or lookupKeyForAsset:fromPackage来查找.

要访问heart.png:

NSString* key = [registrar lookupKeyForAsset:@"icons/heart.png"];
NSString* path = [[NSBundle mainBundle] pathForResource:key ofType:nil];

更复杂的示例可以查看video_payer plugin.

平台Assets

有些时候,可能要直接使用平台的assets.以下有两个示例:

更新应用图标

两端是一样的.

Android:

Flutter的根目录,导航到../android/app/src/main/res.包含ic_launcher.png的目录可以看到.如何替换,可以查看Android规范: Android Developer Guide

IOS

根节点导航到./ios/Runner,Assets.xcassets/AppIcon.appiconset下面就是图标了.通过 Human Interface Guidelines查看

Flutter会使用平台各自的机制来渲染启动屏幕.直接Flutter渲染第一帧.

Android,添加闪屏,到./android/app/src/main/res/drawable/launch_background.xml,可以使用layer list drawable来自定义闪屏.

ios,同样,在自己的目录里添加图片

 

 

 

 

 

### 在 Flutter 中实现将图片上传到应用沙箱的功能 在 Flutter 中,可以通过 `image_picker` 插件来选择本地图片,并使用文件操作库(如 `path_provider`)将图片保存到应用的沙箱中。以下是详细的实现方法: #### 1. 添加依赖 首先,在项目的 `pubspec.yaml` 文件中添加以下依赖: ```yaml dependencies: image_picker: ^0.8.7+3 path_provider: ^2.0.11 ``` 确保使用的版本与当前 Flutter SDK 兼容。 #### 2. 导入必要的库 在 Dart 文件中导入以下库: ```dart import 'dart:io'; import 'package:image_picker/image_picker.dart'; import 'package:path_provider/path_provider.dart'; ``` #### 3. 实现图片选择与保存逻辑 以下是一个完整的代码示例,展示如何选择图片并将其保存到应用沙箱中[^1]: ```dart Future<void> pickAndSaveImage() async { final ImagePicker _picker = ImagePicker(); final XFile? image = await _picker.pickImage(source: ImageSource.gallery); if (image == null) return; final Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); final String appDocumentsPath = appDocumentsDirectory.path; final File originalFile = File(image.path); final String fileName = image.name; final File newFile = await originalFile.copy('$appDocumentsPath/$fileName'); print('图片已保存到沙箱路径: $newFile'); } ``` - `ImagePicker` 用于从设备图库或相机中选择图片。 - `getApplicationDocumentsDirectory()` 获取应用的文档目录路径,这是应用沙箱的一部分。 - `File.copy()` 方法将图片从原始路径复制到沙箱路径。 #### 4. 权限处理 在 Android 和 iOS 平台上,需要申请相应的权限以访问设备存储和保存文件。 ##### Android 配置 在 `AndroidManifest.xml` 文件中添加以下权限: ```xml <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 注意:对于 Android 6.0 及以上版本,还需要动态请求权限[^1]。 ##### iOS 配置 在 `Info.plist` 文件中添加以下键值对: ```xml <key>NSPhotoLibraryUsageDescription</key> <string>需要访问您的相册以选择图片</string> <key>NSCameraUsageDescription</key> <string>需要访问您的相机以拍摄照片</string> ``` #### 5. 示例完整代码 以下是一个完整的示例代码,展示如何在 Flutter 应用中实现图片上传到沙箱的功能: ```dart import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path_provider/path_provider.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('上传图片到沙箱')), body: Center(child: UploadImageButton()), ), ); } } class UploadImageButton extends StatelessWidget { Future<void> _pickAndSaveImage() async { final ImagePicker _picker = ImagePicker(); final XFile? image = await _picker.pickImage(source: ImageSource.gallery); if (image == null) return; final Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); final String appDocumentsPath = appDocumentsDirectory.path; final File originalFile = File(image.path); final String fileName = image.name; final File newFile = await originalFile.copy('$appDocumentsPath/$fileName'); print('图片已保存到沙箱路径: $newFile'); } @override Widget build(BuildContext context) { return ElevatedButton( onPressed: _pickAndSaveImage, child: Text('选择图片并上传到沙箱'), ); } } ``` #### 注意事项 - 确保在运行时正确处理权限请求,尤其是在 Android 和 iOS 上。 - 对于 Web 平台,图片选择的行为可能有所不同,需单独处理。 - 沙箱中的文件仅对应用本身可见,卸载应用后文件可能会被删除。 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值