Flutter 学习之旅 之 flutter 在 Android 端举行简单的图片裁剪操作
目录
Flutter 学习之旅 之 flutter 在 Android 端举行简单的图片裁剪操作
一、简单介绍
二、简单介绍 image_cropper
三、安装 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 插件,用于实现图片裁剪功能。它支持多种裁剪模式和自界说配置,适用于必要让用户在上传图片前举行裁剪的场景。
三、安装 image_picker
1、直接运行命令
使用 Flutter:flutter pub add image_cropper
用到:flutter pub add path_provider
2、或者在 pubspec.yaml 添加
- dependencies:
- image_cropper: ^9.0.0
- path_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
- ...>
- <activity
- android: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">
- <application
- android:label="test_image_crop"
- android:name="${applicationName}"
- android:icon="@mipmap/ic_launcher">
- <activity
- android: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 as
- the Android process has started. This theme is visible to the user
- while the Flutter UI initializes. After that, this theme continues
- to determine the Window background behind the Flutter UI. -->
- <meta-data
- android: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-data
- android:name="flutterEmbedding"
- android:value="2" />
- <activity
- android: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 and
- https://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 {
- @override
- Widget 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'); // 如果裁剪失败,打印错误信息
- }
- }
- @override
- Widget 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('裁剪图片'), // 按钮文字
- ),
- ],
- ),
- ),
- );
- }
- }
复制代码 代码说明
- 资源文件处置惩罚:
- 使用 rootBundle.load 从资源文件加载图片数据,并将其写入临时文件。这是由于 image_cropper 插件必要一个当地文件路径,而不是资源文件路径。
- 裁剪功能:
- 使用 image_cropper 插件的 cropImage 方法打开裁剪界面。
- 配置 AndroidUiSettings 和 IOSUiSettings,设置裁剪界面的样式。
- 设置 lockAspectRatio: false,允许用户自由选择裁剪区域。
- 显示图片:
- 使用 Image.file 显示裁剪后的图片。
- 使用 Image.asset 显示原始图片。
- 使用 BoxFit.contain 确保图片在显示时保持原始比例,不会被拉伸。
- 错误处置惩罚:
- 使用 try-catch 捕获裁剪过程中可能出现的错误,并打印错误信息。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |