Flutter——头像上传功能,实现照片选择及裁剪

2023-11-18

使用两个开发库,image_picker和image_crop。

前者用来拍照或者从相册选择照片,后者用来裁剪,结果均为File类型,裁剪完成后可以直接上传文件。

先写到这儿,有时间上代码。


更新:

实现的功能是点击头像图片,弹出选择框,选择拍照或者从相册中选取:

选择头像上传方式

拍照或选取一张图片后,裁剪到想要大小。进行保存或者上传。

实现:

首先的首先,在Android的manifest文件中,加入网络、相机、文件读写的权限,并在application中加入一个activity声明。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

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

首先在yaml文件中添加依赖:上https://pub.dartlang.org/packages/ flutter第三方插件官网,找最新版即可。添加之后 package get。

在调用的文件导入包,

import 'package:image_picker/image_picker.dart';

点击按钮,进行拍照:

///拍摄照片
Future getImage() async {
  await ImagePicker.pickImage(source: ImageSource.camera)
      .then((image) => cropImage(image));
}

通过相册选取:

///从相册选取
Future chooseImage() async {
  await ImagePicker.pickImage(source: ImageSource.gallery)
      .then((image) => cropImage(image));
}

.then拿到的是拍好的照片,之后进行跳转到剪裁页面CropImageRoute 进行剪裁。

void cropImage(File originalImage) async {
  String result = await Navigator.push(context,
      MaterialPageRoute(builder: (context) => CropImageRoute(originalImage)));
  if (result.isEmpty) {
    print('上传失败');
  } else {
    //result是图片上传后拿到的url
    setState(() {
      iconUrl = result;
      print('上传成功:$iconUrl');
      _upgradeRemoteInfo();//后续数据处理,这里是更新头像信息
    });
  }
}

剪裁页面CropImageRoute 代码:

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_productapp/home/moudel/upload_result.dart';
import 'package:flutter_productapp/home/util/screen.dart';
import 'package:flutter_productapp/base_ui/themes.dart';
import 'package:image_crop/image_crop.dart';

class CropImageRoute extends StatefulWidget {
  CropImageRoute(this.image);

  File image; //原始图片路径

  @override
  _CropImageRouteState createState() => new _CropImageRouteState();
}

class _CropImageRouteState extends State<CropImageRoute> {
  double baseLeft; //图片左上角的x坐标
  double baseTop; //图片左上角的y坐标
  double imageWidth; //图片宽度,缩放后会变化
  double imageScale = 1; //图片缩放比例
  Image imageView;
  final cropKey = GlobalKey<CropState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
      height: Screen.height,
      width: Screen.width,
      color: ThemeColors.color333333,
      child: Column(
        children: <Widget>[
          Container(
            height: Screen.height * 0.8,
            child: Crop.file(
              widget.image,
              key: cropKey,
              aspectRatio: 1.0,
              alwaysShowGrid: true,
            ),
          ),
          RaisedButton(
            onPressed: () {
              _crop(widget.image);
            },
            child: Text('ok'),
          ),
        ],
      ),
    ));
  }

  Future<void> _crop(File originalFile) async {
    final crop = cropKey.currentState;
    final area = crop.area;
    if (area == null) {
      //裁剪结果为空
      print('裁剪不成功');
    }
    await ImageCrop.requestPermissions().then((value) {
      if (value) {
        ImageCrop.cropImage(
          file: originalFile,
          area: crop.area,
        ).then((value) {
          upload(value);
        }).catchError(() {
          print('裁剪不成功');
        });
      } else {
        upload(originalFile);
      }
    });
  }

  ///上传头像
  void upload(File file) {
    print(file.path);
    Dio dio = Dio();
    dio
        .post("http://your ip:port/",
            data: FormData.from({'file': file}))
        .then((response) {
      if (!mounted) {
        return;
      }
      //处理上传结果
      UploadIconResult bean = UploadIconResult(response.data);
      print('上传头像结果 $bean');
      if (bean.code == '1') {
        Navigator.pop(context, bean.data.url);//这里的url在上一页调用的result可以拿到
      } else {
        Navigator.pop(context, '');
      }
    });
  }
}

至此,就可以基本实现了。

有啥问题欢迎指出。

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter——头像上传功能,实现照片选择及裁剪 的相关文章

随机推荐

  • prometheus通过node_exporter抓取的数据准确计算磁盘使用率

    公司使用的openstack的备份服务组件karbor 要查询所使用的备份nas磁盘使用率的需求 根据以前的查询语句 很快写出如下的prom sql 100 topk 1 node filesystem free device 100 no
  • SDRAM详解(结构框图、容量计算、寻址方式、初始化)

    1 SDRM介绍 SDRAM Syncronized Dynamic Ramdam Access Memory 是同步动态随机存储器 是DRAM的升级版 在SDRAM的基础上又发展出DDR double rate 即双倍速度的SDRAM D
  • vue-cli 工程中 访问插槽 数据

    具体解释参考文档 这个插槽啊 怎么说呢 如果你不开发组件 几乎很少用到 甚至用不到 访问插槽呢 使用方法vm slots 插槽名字 如果有的插槽没有名字 则使用vm slots default 访问 打印得到都是数组 得到dom 元素 vm
  • make_moons函数

    生成半环形数据 sklearn datasets make moons n samples 100 shuffle True noise None random state None 参数 n samples 整数型 可选 默认为100 产
  • Java中return、continue和break的区别

    之前一直对return continue break用法有混淆 今日特此学习 1 return 直接跳出当前的方法 返回到该调用的方法的语句处 继续执行 2 break 在循环体内结束整个循环过程 3 continue 结束本次的循环 直接
  • Flame Graphs 火焰图安装与使用

    一 火焰图概述 火焰图 flame graph 是性能分析的利器 通过它可以快速定位性能瓶颈点 perf 命令 performance 的缩写 是 Linux 系统原生提供的性能分析工具 会返回 CPU 正在执行的函数名以及调用栈 stac
  • 380. O(1) 时间插入、删除和获取随机元素

    实现RandomizedSet 类 RandomizedSet 初始化 RandomizedSet 对象 bool insert int val 当元素 val 不存在时 向集合中插入该项 并返回 true 否则 返回 false bool
  • [机缘参悟-74]:沟通技巧-无论在职场还是在家,尽量少用反问句

    目录 反问句的案例 尽量不要使用反问句 避免使用反问词 把反问句改为陈述句 反问句的案例 那天闲聊 邻居老贾向老友们诉苦 老伴今天又用反问句 款待 他了 中午炒菜时 老伴让他拿一瓶油来 老贾问 油瓶在哪里 你觉得油瓶会在哪里 老贾又问 是不
  • 解决k8s集群环境内存不足导致容器被kill问题

    背景 最近线上环境上出现了一个问题 k8s集群环境Pod中的tomcat容器运行一段时间后直接被killd 但有时一切看起来正常 不能准确判断在什么时机出现被Killd问题 本文就此问题介绍了Linux内存不足原因以及为什么特定进程会被杀死
  • nRF24L01单芯片2.4GHz收发模块射频信道频率

    框架图 管脚图 操作模式配置 射频信道频率 RF通道频率决定了 nRF24L01 使用的通道中心 该通道在 1Mbps 时占用 1MHz 带宽 在 2Mbps 时占用 2MHz 带宽 nRF24L01 可以在 2 400GHz 到 2 52
  • poll()函数详解

    poll提供的功能与select类似 不过在处理流设备时 它能够提供额外的信息 include
  • 测试流程简述

    测试流程 整体流程如下 需求评审 功能需求 性能需求 接口需求 测试计划 测试用例 用例评审 测试环境搭建 平台 架构 web服务器 数据库 执行用例 缺陷记录 缺陷跟踪和回归测试 测试报告 测试计划 测试计划 描述了要进行的测试活动的范围
  • 第八站:JavaScript的数据类型、运算符、流程控制语句

    第八站 JavaScript的数据类型 运算符 流程控制语句 欢迎来到第八站 JavaScript的数据类型 运算符 流程控制语句 在这一站 我们将深入探索JavaScript中的核心概念 为你揭示这个语言的奇妙之处 准备好继续冒险了吗 让
  • linux安装datax

    1 创建文件夹 存放安装包 cd opt mkdir datax cd datax 2 下载安装包 wget http datax opensource oss cn hangzhou aliyuncs com datax tar gz 3
  • 流程引擎是什么?有什么作用?

    编者按 本文详细论述了流程引擎的概念 流程引擎的作用以及选型的要旨 并介绍了自主研发具有中国特色的流程引擎 关键词 流程引擎 集成性 数据分析 BPMN2 0规范 中国特色 流程审批 自主研发 流程引擎是什么 流程引擎 用来驱动业务按照设定
  • Python基础语法(函数式编程)

    目录 实例1 温度转换 实例2 蟒蛇绘制 模块1 turtle库 基本图形绘制 基本数据类型 1 整数 浮点数 复数 1 整数 2 浮点数 3 复数 4 数值运算操作符 实例3 天天向上的力量 2 字符串 模块2 time库 时间的基本处理
  • SpringCloud文件上传

    2 实现图片上传 刚才的新增实现中 我们并没有上传图片 接下来我们一起完成图片上传逻辑 文件的上传并不只是在品牌管理中有需求 以后的其它服务也可能需要 因此我们创建一个独立的微服务 专门处理各种上传 2 1 搭建项目 2 1 1 创建Spr
  • Android:播放UDP流例如udp://@239.0.0.3:8218

    成功实现播放udp github下载 求大佬们给个star GitHub YangWenlong71 udpplayer 基于ijk重新编译 未做删减几乎全能的安卓视频播放器 支持播放UDP https http 等 分割线 研究思路及结果
  • Django(17):Cookie 和 Session

    目录 Cookie 什么是Cookie Django使用Cookie Cookie使用示例 session 什么是session Django使用session Session使用示例 小结 HTTP协议本身是 无状态 的 在一次请求和下一
  • Flutter——头像上传功能,实现照片选择及裁剪

    使用两个开发库 image picker和image crop 前者用来拍照或者从相册选择照片 后者用来裁剪 结果均为File类型 裁剪完成后可以直接上传文件 先写到这儿 有时间上代码 更新 实现的功能是点击头像图片 弹出选择框 选择拍照或