Android 设置头像 - 裁剪及圆形头像

    书接上文 Android 设置头像 - 相册拍照,通过相册和照片的设置就可以获取到需要的头像信息,但是在通常情况下,我们还想要实现针对头像的裁剪功能和圆形头像功能。

先上截图:
在这里插入图片描述

图像裁剪

    通常裁剪可以分为程序自动裁剪和用户选择裁剪两种方式,程序自动裁剪及程序中设置固定的裁剪比例然后系统自动进行裁剪,Glide即可实现该功能。但这种实现方式往往不能满足用户实际需求,及实际裁剪需要用户进行选择图片裁剪范围。下面将提供两种图片裁剪的实现逻辑,出了本文描述的裁剪实现逻辑外还有自定义裁剪view等其他实现逻辑,由于技术有限,再次仅仅阐述较为简单的两种实现逻辑。

第三方裁剪库

    目前存在很对开源的第三方Android裁剪工具库,通过比较uCrop的裁剪工具库较为流行,本文将以该裁剪工具集成为例进行说明。uCrop的GitHub地址点这里。通过README文档可知,集成该工具需要以下操作:

  • gradle引入
  • AndroidManifest.xml中声明Activity
  • 业务代码中调用UCrop进行裁剪
  • 通过onActivityResult接收裁剪结果intent

    上述四个过程在github中作者都进行了详细说明,下面进行我理解的简单说明:
采用该工具需要传入目标Uri
    使用该工具进行裁剪需要输入源Uri和目标Uri,及被参见图片Uri和裁剪后图片存放的Uri,不同Android版本的Uri获取方式不同,Uri相关内容本人也一知半解,后续了解后将另文说明。
AndroidManifest.xml中声明Activity
    相信使用module开发或者引入过arr资源包的都清楚需要在AndroidManifest.xml中引入第三方arr的Activity文件。根据这个说明不难推断出Ucrop为一个arr资源包并非jar包,并且结合网上了解到的自定义裁剪试图的实现逻辑不难推断出,Ucrop也实现了一个自定义Activity进行裁剪,当用户发起裁剪请求时,将跳转到Ucrop的Activity中,待裁剪完成后进行回跳并携带裁剪结果。

通过onActivityResult接收裁剪结果intent
    UCrop.start()方法将进行裁剪,通过查看源码,该方法调用了activity.startActivityForResult(getIntent(activity), requestCode);方法,因此需要重写onActivityResult方法进行接收回跳携带参数。但是由于startActivityForResult即将弃用,所以这种方式我不建议使用。考虑是否可以通过重写UCrop.start方法通过ActivityResultLauncher.launch的方法进行裁剪调用。

系统默认裁剪intent调用

    系统默认裁剪实现是裁剪过程中最简单的实现方式,按照百度结果只需要创建一个Intent intent = new Intent(“com.android.camera.action.CROP”);意图并进行相关参数配置即可。下面首先展示我的实现逻辑

  • 首先配置ActivityResultContract如下
/*** 裁剪照片的contract** @author baiyang* @since 2024-04-28*/
public class CropImageResultContract extends ActivityResultContract<Intent, Intent> {public static final String AUTHORITY = "com.ldr.imosApp.provider";public static final String IMAGE_TYPE = "image/jpeg";public static final String JPG_TYPE = "jpg";private String type;private Uri uri;@NonNull@Overridepublic Intent createIntent(@NonNull Context context, Intent input) {input.putExtra("crop", "true");input.putExtra("aspectX", 1);input.putExtra("aspectY", 1);input.putExtra("outputX", 256);input.putExtra("outputY", 256);input.putExtra("return-data", true);String mimeType = null;String fileName = null;mimeType = IMAGE_TYPE;fileName = System.currentTimeMillis() + "." + JPG_TYPE;Uri mediaUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {ContentValues values = new ContentValues();values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);uri = context.getContentResolver().insert(mediaUri, values);} else {uri = FileProvider.getUriForFile(context, AUTHORITY,new File(context.getExternalCacheDir().getAbsolutePath(), fileName));}input.putExtra(MediaStore.EXTRA_OUTPUT, uri);return input;}/*** 返回拍照结果,因为在调用相机的过程中设置了EXTRA_OUTPUT,因此返回时intent=null,需要重新设置一下** @param resultCode* @param intent* @return*/@Overridepublic Intent parseResult(int resultCode, @Nullable Intent intent) {if (resultCode != Activity.RESULT_OK) {return null;}intent = new Intent();intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);return intent;}
}

    上述代码在拍照图库文档中已经进行详细说明,在此需要补充一点疏漏是:我们在createIntent方法中创建了一个Uri,那么intent返回的时候通过getData就不能获取裁剪结果的Uri了,而且我们创建的这个Uri会导致裁剪后的图片将作为一个资源存放到了我们的通过中,这也是为什么在Android 设置头像 - 相册拍照一文从图库中选择照片的createIntent方法中我没有创建Uri的原因,如果创建了会导致图库中存在两张重复的图片。在上述代码实现初期,我并没有创建Uri,直接通过getData进行获取Uri,在模拟器上进行测试是可以通过的,但是使用真机测试的过程中依旧会出现裁剪正常进行,但是裁剪结果getData=null的情况。目前原因不详,怀疑可能是通过intent调用默认的裁剪实现后,裁剪的返回结果在不同机型上进行了不同方式的返回,因此通过创建Uri进行接收裁剪结果是最稳妥的实现方式

  • 进行裁剪结果回调函数实现
    /*** 裁剪照片的回调函数*/private final ActivityResultCallback<Intent> cropCallback = result -> {if (Objects.nonNull(result)) {Uri uri = result.getParcelableExtra(MediaStore.EXTRA_OUTPUT);Glide.with(PersonalInformationActivity.this).load(uri).into(binding.headSculpture);} else {LogUtils.e("裁剪照片回调失败,未回传相关数据");}};

即获取结果后直接通过Glide进行图片回显。后续的圆形图像可以通过Glide进行实现。

  • intent调用
        在进行intent调用之前首先需要获取ActivityResultLauncher,如下:
        cropResultLauncher = registerForActivityResult(new CropImageResultContract(),cropCallback);

    intent调用是需要进行裁剪,而裁剪过程应该是在选择图片或者拍照后进行,因此需要修改原拍照图库的回调函数进行调用裁剪的intent,代码如下:

    /*** 拍照或者选择图库照片后回调*/private final ActivityResultCallback<Intent> callback = result -> {if (Objects.nonNull(result)) {Uri uri = result.getParcelableExtra(MediaStore.EXTRA_OUTPUT);// 进行裁剪Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");cropResultLauncher.launch(intent);
//            Glide.with(getApplicationContext()).load(uri).into(binding.headSculpture);} else {LogUtils.e("拍照、录像数据回调失败,未回传相关数据");}};

    上述及使用系统默认的裁剪工具进行裁剪的实现方式,不同手机,不同android版本的系统默认裁剪工具并不相同,因此最终实现效果也不相同,由于手头真机数量有限,并不能针对更多机型进行测试,所以并不确定上述逻辑实现可以适配所以手机,而且对于没有系统默认裁剪工具的机型,上述代码无法进行裁剪,而Ucrop工具可以实现裁剪。

intent到底是什么?

    Intent(意图)主要是解决Android应用的各项组件之间的通讯。
    Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给被调用的组件,并完成组件的调用。
    因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。

    上面为百度词条对其的解释,intent可以实现各个组件的通信。回忆我们实现的Activity跳转逻辑,通过startActivity(intent);方法进行跳转,intent我们一般进行下面定义:

Intent intent = new Intent();
intent.setClass(getApplicationContext(), MainActivity.class);

    上述代码表示从当前Activity跳转到MainActivity,可以看到我们并没有进行MainActivity初始化跳转等特殊设置,我没有深入研究Android底层源码,但是不难推测出当startActivity(intent);方法被调用后,intent意图交由Android底层进行处理,Android系统根据intent传参判断该意图需求,如果是Activity跳转,则从Activity注册表中获取目的Activity并进行生命周期的调用(个人揣测,不准欢迎斧正)。
    上面例子为Activity跳转,一般都是同一APP内部跳转,但是当我们进行拍照、调用通讯录等系统级别的操作时也是借助Intent进行实现的,那么可以大胆推测,intent的处理时交由Android底层进行处理,他并不是某个app内部进行处理的,当底层接收到一个访问相机的intent时,将判断是否具备访问权限,如果具备则调用相机。
    通过上述分析,我们可以继续推测调用系统裁剪及Intent intent = new Intent(“com.android.camera.action.CROP”);这个意图在交由Android底层进行处理的时候,Android底层将从它的Activity注册表中找到相关Activity进行跳转。在此引申下属代码:

        <activityandroid:name=".ui.GuideActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>

    这段代码写Android的都清楚,Android首界面的设置,设置Android受界面需要声明intent-filter标签,并且需要设置android:exported=“true”,表明该Activity允许外部访问(及允许Android底层进行调用启动)。

圆形头像

    圆形头像的实现可记住Glide工具,按照如下代码:

            RequestOptions options = new RequestOptions().circleCropTransform();Glide.with(PersonalInformationActivity.this).load(uri).apply(options).into(binding.headSculpture);

    在进行into到目标view的过程中Glide使用了bitmapTransform进行转化,使用的是CropCircleTransformation实现,该实现类将图片转化为圆形图片。通过借助Glide的实现圆形头像较为简单,在此不再深入Gilde的具体细节。

总结

    通过裁剪和圆形头像的实现更加深入的对ActivityResultLauncher进行了学习,并在实现的过程中对Intent有了更加深入的思考,如果本文内容存在问题欢迎各位大佬进行斧正。总结本文内容。

  • Ucrop工具实现图片裁剪
  • Intent系统默认裁剪实现类
  • intent深入思考
  • Gilde圆形图片的实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/317977.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LT6911GX HDMI2.1 至四端口 MIPI/LVDS,带音频 龙迅方案

1. 描述LT6911GX 是一款面向 VR / 显示应用的高性能 HDMI2.1 至 MIPI 或 LVDS 芯片。HDCP RX作为HDCP中继器的上游&#xff0c;可以与其他芯片的HDCP TX配合使用&#xff0c;实现中继器功能。对于 HDMI2.1 输入&#xff0c;LT6911GX 可配置为 3/4 通道。自适应均衡功能使其适合…

Redis运维篇-快速面试笔记(速成版)

文章目录 1. Redis的持久化1.1 RDB&#xff08;快照模式&#xff09;1.2 AOF 模式 2. Redis主从模型&#xff08;高可用&#xff09;2.1 Redis的主从复制2.2 Redis拓扑结构 3. Redis集群模式&#xff08;高并发&#xff09;3.1 Redis的Slots3.2 集群模式的常用命令3.3 多主多从…

全景剖析阿里云容器网络数据链路(七):Terway DataPath V2(Terway≥1.8.0)

作者&#xff1a;余凯 前言 近几年&#xff0c;企业基础设施云原生化的趋势越来越强烈&#xff0c;从最开始的IaaS化到现在的微服务化&#xff0c;客户的颗粒度精细化和可观测性的需求更加强烈。容器网络为了满足客户更高性能和更高的密度&#xff0c;也一直在高速的发展和演…

2024年五一数学建模C题完整解题思路代码

2024年第二十一届五一数学建模竞赛题目 C题 煤矿深部开采冲击地压危险预测 煤炭是中国的主要能源和重要的工业原料。然而&#xff0c;随着开采深度的增加&#xff0c;地应力增大&#xff0c;井下煤岩动力灾害风险越来越大&#xff0c;严重影响着煤矿的安全高效开采。在各类深…

MySQL之多表查询

1. 前言 多表查询&#xff0c;也称为关联查询.指两个或两个以上的表一起完成查询操作.前提条件 : 这些一起查询的表之间是有关系的(一对一/一对多).他们之间一定是有关联字段&#xff0c;这个关联字段可能建立了外键&#xff0c;也可能没有建立外键. 2. 笛卡尔积现象(交叉连接…

【Vulhub靶场】Nginx 漏洞复现

Nginx 漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09;1、影响版本2、漏洞原理3、漏洞复现 二、Nginx 解析漏洞1、版本信息&#xff1a;2、漏洞详情3、漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09; 1、影响版本 Nginx …

【数据结构】:链表的带环问题

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构 &#x1f337;追光的人&#xff0c;终会万丈光芒 前言&#xff1a; 链表的带环问题在链表中是一类比较难的问题&#xff0c;它对我们的思维有一个比较高的要求&#xff0c;但是这一类…

【数据结构】链表专题3

前言 本篇博客我们继续来讨论链表专题&#xff0c;今天的链表算法题是经典中的经典 &#x1f493; 个人主页&#xff1a;小张同学zkf ⏩ 文章专栏&#xff1a;数据结构 若有问题 评论区见&#x1f4dd; &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐文章 目录 1.判断链表是否…

【Scala---01】Scala『 Scala简介 | 函数式编程简介 | Scala VS Java | 安装与部署』

文章目录 1. Scala简介2. 函数式编程简介3. Scala VS Java4. 安装与部署 1. Scala简介 Scala是由于Spark的流行而兴起的。Scala是高级语言&#xff0c;Scala底层使用的是Java&#xff0c;可以看做是对Java的进一步封装&#xff0c;更加简洁&#xff0c;代码量是Java的一半。 因…

操作系统安全:Linux安全审计,Linux日志详解

「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等12个知识域的一百多个知识点,持续更新。 这一章节需要直到Linux…

09_Scala函数和对象

文章目录 函数和对象1.函数也是对象 scala中声明了一个函数 等价于声明一个函数对象2.将函数当作对象来用&#xff0c;也就是访问函数&#xff0c;但是不执行函数结果3.对象拥有数据类型(函数类型)&#xff0c;对象可以进行赋值操作4.函数对象类型的省略写法&#xff0c;也就是…

Java创建并遍历N叉树(前序遍历)

力扣 title589&#xff1a;N叉树的前序遍历 给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示&#xff0c;每组子节点由空值 null 分隔&#xff08;请参见示例&#xff09;。 思路&#xff1a; 1.初始化时…

CSS-复合选择器

作用&#xff1a; 后代选择器&#xff1a; 子代选择器 并集选择器 用逗号隔开&#xff0c;在style里面写的时候&#xff0c;每一个标签空一行。 <title>Document</title><style>p,div,span{color: aqua;}</style> </head> <body><p>…

细说SVPWM原理及软件实现原理,关联PWM实现

细说SVPWM原理及软件实现原理&#xff0c;关联PWM实现 文章目录 细说SVPWM原理及软件实现原理&#xff0c;关联PWM实现1. 前言2. 基础控制原理回顾2.1 FOC 原理回顾2.2 细说 SVPWM2.2.1 矢量扇区计算2.2.2 矢量作用时间计算 2.2.3 如何理解 U4 U6 2/3Udc?2.2.4 如何理解 U4m…

工业异常检测

工业异常检测在业界和学界都一直是热门&#xff0c;近期其更是迎来了全新突破&#xff1a;与大模型相结合&#xff01;让异常检测变得更快更准更简单&#xff01; 比如模型AnomalyGPT&#xff0c;它克服了以往的局限&#xff0c;能够让大模型充分理解工业场景图像&#xff0c;判…

Java中使用Redis实现分布式锁的三种方式

1. 导语 随着软件开发领域的不断演进,并发性已经成为一个至关重要的方面,特别是在资源跨多个进程共享的分布式系统中。 在Java中,管理并发性对于确保数据一致性和防止竞态条件至关重要。 Redis作为一个强大的内存数据存储,为在Java应用程序中实现分布式锁提供了一种高效的…

第11章 数据库技术(第一部分)

一、数据库技术术语 &#xff08;一&#xff09;术语 1、数据 数据描述事物的符号描述一个对象所用的标识&#xff0c;可以文字、图形、图像、语言等等 2、信息 现实世界对事物状态变化的反馈。可感知、可存储、可加工、可再生。数据是信息的表现形式和载体&#xff0c;信…

Mac brew安装Redis之后更新配置文件的方法

安装命令 brew install redis 查看安装位置命令 brew list redis #查看redis安装的位置 % brew list redis /usr/local/Cellar/redis/6.2.5/.bottle/etc/ (2 files) /usr/local/Cellar/redis/6.2.5/bin/redis-benchmark /usr/local/Cellar/redis/6.2.5/bin/redis-check-ao…

【PyTorch 实战3:YOLOv5检测模型】10min揭秘 YOLOv5 检测网络架构、工作原理以及pytorch代码实现(附代码实现!)

YOLOv5简介 YOLOv5&#xff08;You Only Look Once, Version 5&#xff09;是一种先进的目标检测模型&#xff0c;是YOLO系列的最新版本&#xff0c;由Ultralytics公司开发。该模型利用深度学习技术&#xff0c;能够在图像或视频中实时准确地检测出多个对象的位置及其类别&…

win下vscode的vim切换模式的中英文切换

问题描述 在vscode中安装vim插件后&#xff0c;如果insert模式下完成输入后&#xff0c;在中文输入方式下按esc会发生无效输入&#xff0c;需要手动切换到英文。 解决方法 下载完成vscode并在其中配置vim插件下载github—im-select.exe插件&#xff08;注意很多博文中的gitcod…