Flutter 学习之旅 之 flutter 在 Android 端进行简单的图片裁剪操作

ops/2025/3/1 20:18:06/

flutter%20%E5%9C%A8%20Android%20%E7%AB%AF%E8%BF%9B%E8%A1%8C%E7%AE%80%E5%8D%95%E7%9A%84%E5%9B%BE%E7%89%87%E8%A3%81%E5%89%AA%E6%93%8D%E4%BD%9C" name="Flutter%20%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%97%85%20%E4%B9%8B%20flutter%20%E5%9C%A8%20Android%20%E7%AB%AF%E8%BF%9B%E8%A1%8C%E7%AE%80%E5%8D%95%E7%9A%84%E5%9B%BE%E7%89%87%E8%A3%81%E5%89%AA%E6%93%8D%E4%BD%9C">Flutter 学习之旅 之 flutter 在 Android 端进行简单的图片裁剪操作

目录

flutter%20%E5%9C%A8%20Android%20%E7%AB%AF%E8%BF%9B%E8%A1%8C%E7%AE%80%E5%8D%95%E7%9A%84%E5%9B%BE%E7%89%87%E8%A3%81%E5%89%AA%E6%93%8D%E4%BD%9C-toc" name="tableOfContents" style="margin-left:0px">Flutter 学习之旅 之 flutter 在 Android 端进行简单的图片裁剪操作

一、简单介绍

二、简单介绍 image_cropper

flutter-toc" name="tableOfContents" style="margin-left:80px">三、安装 image_picker

四、简单案例实现

五、关键代码


一、简单介绍

Flutter 是一款开源的 UI 软件开发工具包,由 Google 开发和维护。它允许开发者使用一套代码同时构建跨平台的应用程序,包括移动设备(iOS 和 Android)、Web 和桌面平台(Windows、macOS 和 Linux)。

Flutter 使用 Dart 编程语言,它可以将代码编译为 ARM 或 Intel 机器代码以及 JavaScript,从而实现快速的性能。Flutter 提供了一个丰富的预置小部件库,开发者可以根据自己的需求灵活地控制每个像素,从而创建自定义的、适应性强的设计,这些设计在任何屏幕上都能呈现出色的外观和感觉。

二、简单介绍 image_cropper

网址:image_cropper | Flutter package

image_cropper 是一个功能强大的 Flutter 插件,用于实现图片裁剪功能。它支持多种裁剪模式和自定义配置,适用于需要让用户在上传图片前进行裁剪的场景。

flutter" name="%E4%B8%89%E3%80%81%E5%AE%89%E8%A3%85%20webview_flutter" style="background-color:transparent">三、安装 image_picker

1、直接运行命令

使用 Flutter:flutter pub add image_cropper

用到:flutter pub add path_provider

2、或者在 pubspec.yaml 添加

dependencies:image_cropper: ^9.0.0path_provider: ^2.1.5

四、简单案例实现

1、这里使用 Android Studio 进行创建 Flutter 项目

2、创建一个 application 的 Flutter 项目

3、工程创建后如下

4、在 lib/main.dart 编写代码实现图片显示,然后进行简单裁剪

5、添加图片

assets 也可以叫做资源。资源是与您的应用程序一起捆绑和部署的文件,可在运行时访问。常见的资源类型包括静态数据(例如 JSON 文件)、配置文件、图标和图像(JPEG、WebP、GIF、动画 WebP/GIF、PNG、BMP 和 WBMP)。

每个资源都由资源文件所在的显式路径(相对于 pubspec.yaml 文件)标识。声明资源的顺序无关紧要。包含资源的目录名称无关紧要。

在构建过程中,Flutter 将资源放入一个名为资源包的特殊存档中,应用程序会在运行时从中读取。

Flutter 使用位于项目根目录的 pubspec.yaml 文件来识别应用程序所需的资源。

资源文件夹的名称是随意的,我们可以把资源文件夹放在和 lib 平级的根目录下面,为图片建立文件夹 images,把上面示例中的猫头鹰图片放入其中。

修改 pubspec.yaml 的配置

flutter:assets:- images/imagename.png

在代码中可以通过 images/imagename.png 使用图片。

Image.asset('images/owl.png',width: 200,height: 200,
);

当你发布应用程序的时候,pubspec.yaml 中配置的图片会和代码一起打包发布。

如果有很多图片,这样一张一张注册很是麻烦,我们可以直接指定文件夹。比如我们可以一次性注册 images 文件夹下面的所有图片。

flutter:assets:- images/

6、这里用到 image_cropper,所以需要声明 UCropActivity

AndroidManifest.xml 中声明 UCropActivity,否则 image_cropper 插件可能无法正常工作:

<application...><activityandroid:name="com.yalantis.ucrop.UCropActivity"android:screenOrientation="portrait"android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
</application>

完整的参考如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"><applicationandroid:label="test_image_crop"android:name="${applicationName}"android:icon="@mipmap/ic_launcher"><activityandroid:name=".MainActivity"android:exported="true"android:launchMode="singleTop"android:taskAffinity=""android:theme="@style/LaunchTheme"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:windowSoftInputMode="adjustResize"><!-- Specifies an Android theme to apply to this Activity as soon asthe Android process has started. This theme is visible to the userwhile the Flutter UI initializes. After that, this theme continuesto determine the Window background behind the Flutter UI. --><meta-dataandroid:name="io.flutter.embedding.android.NormalTheme"android:resource="@style/NormalTheme"/><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><!-- Don't delete the meta-data below.This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --><meta-dataandroid:name="flutterEmbedding"android:value="2" /><activityandroid:name="com.yalantis.ucrop.UCropActivity"android:screenOrientation="portrait"android:theme="@style/Theme.AppCompat.Light.NoActionBar"/></application><!-- Required to query activities that can process text, see:https://developer.android.com/training/package-visibility andhttps://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. --><queries><intent><action android:name="android.intent.action.PROCESS_TEXT"/><data android:mimeType="text/plain"/></intent></queries>
</manifest>

7、连接设备,运行项目,简单效果如下

五、关键代码

import 'dart:io'; // 导入 Dart 的文件操作库,用于文件读写
import 'package:flutter/material.dart'; // 导入 Flutter 的 Material 组件库
import 'package:image_cropper/image_cropper.dart'; // 导入 image_cropper 插件,用于裁剪图片
import 'package:path_provider/path_provider.dart'; // 导入 path_provider 插件,用于获取临时目录路径
import 'package:flutter/services.dart'; // 导入 Flutter 的服务库,用于加载资源文件void main() {runApp(MyApp()); // 启动应用
}// 定义一个无状态的 MyApp 组件
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Image Cropper Demo', // 应用标题theme: ThemeData(primarySwatch: Colors.blue, // 设置主题颜色为蓝色),home: ImageCropperDemo(), // 设置首页为 ImageCropperDemo 页面);}
}// 定义一个有状态的 ImageCropperDemo 组件
class ImageCropperDemo extends StatefulWidget {@override_ImageCropperDemoState createState() => _ImageCropperDemoState();
}class _ImageCropperDemoState extends State<ImageCropperDemo> {CroppedFile? _croppedFile; // 用于存储裁剪后的图片文件final String _imageAssetPath = 'images/sunwukongd.jpg'; // 替换为你的图片路径// 将资源文件复制到临时路径Future<File> _copyAssetToTemp(String assetPath) async {final tempDir = await getTemporaryDirectory(); // 获取设备的临时目录路径final tempFilePath = '${tempDir.path}/temp_image.jpg'; // 定义临时文件路径final ByteData data = await rootBundle.load(assetPath); // 从资源文件加载图片数据final bytes = data.buffer.asUint8List(); // 将图片数据转换为字节列表await File(tempFilePath).writeAsBytes(bytes); // 将字节数据写入临时文件return File(tempFilePath); // 返回临时文件对象}// 裁剪图片的方法Future<void> _cropImage() async {try {final tempFile = await _copyAssetToTemp(_imageAssetPath); // 将资源文件复制到临时路径// 调用 ImageCropper 裁剪图片final croppedFile = await ImageCropper().cropImage(sourcePath: tempFile.path, // 指定裁剪的源图片路径uiSettings: [AndroidUiSettings( // 配置 Android 裁剪界面的样式toolbarTitle: '裁剪图片', // 工具栏标题toolbarColor: Colors.blue, // 工具栏背景颜色toolbarWidgetColor: Colors.white, // 工具栏文字颜色initAspectRatio: CropAspectRatioPreset.original, // 初始裁剪比例为原始图片比例lockAspectRatio: false, // 不锁定裁剪比例,允许自由裁剪),IOSUiSettings( // 配置 iOS 裁剪界面的样式title: '裁剪图片', // 裁剪界面标题),],);if (croppedFile != null) { // 如果裁剪成功setState(() {_croppedFile = croppedFile; // 更新裁剪后的图片文件});}} catch (e) {print('裁剪失败: $e'); // 如果裁剪失败,打印错误信息}}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Image Cropper Demo'), // 设置应用栏标题),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, // 垂直居中对齐children: [// 显示裁剪后的图片if (_croppedFile != null) // 如果裁剪后的图片不为空Image.file(File(_croppedFile!.path), // 显示裁剪后的图片width: 300, // 图片宽度height: 300, // 图片高度fit: BoxFit.contain, // 使用 BoxFit.contain 保持图片比例)else // 如果裁剪后的图片为空,显示原始图片Image.asset(_imageAssetPath, // 显示原始图片width: 300, // 图片宽度height: 300, // 图片高度fit: BoxFit.contain, // 使用 BoxFit.contain 保持图片比例),SizedBox(height: 20), // 添加间距ElevatedButton(onPressed: _cropImage, // 点击按钮触发裁剪操作child: Text('裁剪图片'), // 按钮文字),],),),);}
}

代码说明

  1. 资源文件处理

    • 使用 rootBundle.load 从资源文件加载图片数据,并将其写入临时文件。这是因为 image_cropper 插件需要一个本地文件路径,而不是资源文件路径。

  2. 裁剪功能

    • 使用 image_cropper 插件的 cropImage 方法打开裁剪界面。

    • 配置 AndroidUiSettingsIOSUiSettings,设置裁剪界面的样式。

    • 设置 lockAspectRatio: false,允许用户自由选择裁剪区域。

  3. 显示图片

    • 使用 Image.file 显示裁剪后的图片。

    • 使用 Image.asset 显示原始图片。

    • 使用 BoxFit.contain 确保图片在显示时保持原始比例,不会被拉伸。

  4. 错误处理

    • 使用 try-catch 捕获裁剪过程中可能出现的错误,并打印错误信息。


http://www.ppmy.cn/ops/162318.html

相关文章

vue+element ui 实现选择季度组件

1、实现效果 和element ui 选择月份同样的效果&#xff0c;也支持键盘上下左右控制选择季度。 2、页面调用 <ElQuarterPicker v-model"value" placeholder"选择季度"></ElQuarterPicker> 3、组件代码&#xff1a; ElQuarterPicker.vue &l…

华为在不同发展时期的战略选择(节选)

华为在不同发展时期的战略选择&#xff08;节选&#xff09; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 来源&#xff1a;谢宁专著《华为战略管理法&#xff1a;DSTE实战体系》。本文有节选修改。 导言 从目前所取得的成就往回看&#xff0c;华为…

C语言【进阶篇】之指针——涵盖基础、数组与高级概念

目录 &#x1f680;前言&#x1f914;指针是什么&#x1f31f;指针基础&#x1f4af;内存与地址&#x1f4af;指针变量&#x1f4af; 指针类型&#x1f4af;const 修饰指针&#x1f4af;指针运算&#x1f4af;野指针和 assert 断言 &#x1f4bb;数组与指针&#x1f4af;数组名…

深度学习基础--ResNet50V2网络的讲解,ResNet50V2的复现(pytorch)以及用复现的ResNet50做鸟类图像分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 如果说最经典的神经网络&#xff0c;ResNet肯定是一个&#xff0c;从ResNet发布后&#xff0c;作者又进行修改&#xff0c;命名为ResNe50v2&#xff0c…

Cursor+pycharm接入Codeuim(免费版),Tab自动补全功能平替

如题&#xff0c;笔者在Cursor中使用pycharm写python程序&#xff0c;试用期到了Tab自动补全功能就不能用了&#xff0c;安装Codeuim插件可以代替这个功能。步骤如下&#xff1a; 1. 在应用商店中搜索扩展Codeuim&#xff0c;下载安装 2. 安装完成后左下角会弹出提示框&#x…

用HTML5+CSS+JavaScript实现新奇挂钟动画

用HTML5+CSS+JavaScript实现新奇挂钟动画 引言 在技术博客中,如何吸引粉丝并保持他们的关注?除了干货内容,独特的视觉效果也是关键。今天,我们将通过HTML5、CSS和JavaScript实现一个新奇挂钟动画,并将其嵌入到你的网站中。这个动画不仅能让你的网站脱颖而出,还能展示你的…

GitHub开源协议选择指南:如何为你的项目找到最佳“许可证”?

引言 当你站在GitHub仓库创建的十字路口时&#xff0c;是否曾被众多开源协议晃花了眼&#xff1f; 别担心&#xff01;这篇指南将化身你的"协议导航仪"&#xff0c;用一张流程图五个灵魂拷问&#xff0c;帮你轻松找到最佳选择。无论你是开发者、开源爱好者&#xff…

告别GitHub连不上!一分钟快速访问方案

一、当GitHub抽风时&#xff0c;你是否也这样崩溃过&#xff1f; &#x1f621; npm install卡在node-sass半小时不动&#x1f62d; git clone到90%突然fatal: early EOF&#x1f92c; 改了半天hosts文件&#xff0c;第二天又失效了... 根本原因&#xff1a;传统代理需要复杂…