基于PhotoView的头像/圆形裁剪控件
常见的图片裁剪有两种,一种是图片固定,裁剪框移动放缩来确定裁剪区域,早期见的比较多,缺点在于不能直接预览裁剪后的效果;还有一种现在比较普遍了,就是裁剪框固定,直接拖动缩放图片,便于预览裁剪结果。
我做的这个控件属于后者。一般来说,做图片裁剪的思路无外乎是先监听手势,获取坐标,再对图片变形,最后确定裁剪区域的坐标对位图进行裁剪,最后保存图片到本地。我嘛还是个技术小白,一想到要监控手势这些就头疼,碰巧项目之前为了做查看大图而引入了大名鼎鼎的第三方图片查看控件——PhotoView。于是转念一想,能不能把到图片变形为止的前几步交给PhotoView来搞定,我只要负责确定确定裁剪区域后面这几步呢。后来掉了好几个坑导致偷懒也没轻松多少其实ε=(´ο`*)))唉~

先简要介绍一下设计思路,如上图所示,主要分为两部分,上层是遮罩(也可以理解为是裁剪框),用于预览裁剪后的效果;下层是PhotoView,这里多包了一层改为正方形显示。
下面是遮罩的代码,比较简单,这里就不赘述了。
/**
* Created by MandyLu on 2018/7/14.
* 圆形裁剪框
*/
public class CircleCropView extends View {
public final int CIRCLE_MARGIN = 50; public CircleCropView(Context context) {
super(context);
} public CircleCropView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
} public CircleCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
} @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CircleCropView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
} @RequiresApi(api = Build.VERSION_CODES.O)
@Override
protected void onDraw(Canvas canvas) {
canvas.save(); Path path = new Path();
Rect viewDrawingRect = new Rect();
getDrawingRect(viewDrawingRect); float radius = viewDrawingRect.width() / 2 - CIRCLE_MARGIN;
path.addCircle(viewDrawingRect.left + radius + CIRCLE_MARGIN,
viewDrawingRect.top + radius + CIRCLE_MARGIN, radius, Path.Direction.CW); Paint outsidePaint = new Paint();
outsidePaint.setAntiAlias(true);
outsidePaint.setARGB(151, 0, 0, 0); canvas.clipPath(path, Region.Op.DIFFERENCE);
canvas.drawRect(viewDrawingRect, outsidePaint);
canvas.restore();
}
}
SquarePhotoView只是在PhotoView的基础上改了长宽,重写一下onMeasure方法即可:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
那么现在最关键的一步,就是从PhotoView获取当前图片显示区域的Drawable或Bitmap了。粗略看了一下PhotoView的函数,并没有找到能用的(囧)。解决第一个坑的笨办法就是,自己动手丰衣足食——直接拿原图的bitmap,然后问PhotoView要当前图片的变形矩阵,自个儿通过矩阵一步步变形拿到对应的位图。
思路其实是没问题的,然而第二个坑又出现了(囧)。这里的变形矩阵,我最早百度的结果是getSuppMatrix,源码我没有细看,但掉坑的过程中据我观察,猜测应该是对应最新一次的手势变形结果(不确定= =,也可能是其他坑综合导致的错误结果)。总之最后我查了一会源码,最终确定用的是getDisplayMatrix。
紧接着是第三个坑,坑多了就习惯了。矩阵中的XY位移量,我起初以为是显示区域中心相对于原图中心的位移,即如果仅有缩放操作的话,位移应该为0。但实际通过特殊位置(例如取四个顶点)的裁剪结果来看,这里的XY位移量实际最后显示区域左上角的点相对原点(即原图左上角)的位移,简单点说,可以把位移量作为最终显示区域左上角的坐标。
然后我就迎来了第四个坑(
基于PhotoView的头像/圆形裁剪控件的更多相关文章
- Android开发技巧——定制仿微信图片裁剪控件
拍照--裁剪,或者是选择图片--裁剪,是我们设置头像或上传图片时经常需要的一组操作.上篇讲了Camera的使用,这篇讲一下我对图片裁剪的实现. 背景 下面的需求都来自产品. 裁剪图片要像微信那样,拖动 ...
- [UWP]如何实现UWP平台最佳图片裁剪控件
前几天我写了一个UWP图片裁剪控件ImageCropper(开源地址),自认为算是现阶段UWP社区里最好用的图片裁剪控件了,今天就来分享下我编码的过程. 为什么又要造轮子 因为开发需要,我们需要使用一 ...
- 基于存储过程的MVC开源分页控件--LYB.NET.SPPager
摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件MVCPager(http://www.webdiyer.com/)算 ...
- FineUI 基于 ExtJS 的专业 ASP.NET 控件库
FineUI 基于 ExtJS 的专业 ASP.NET 控件库 http://www.fineui.com/
- 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>
上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...
- 基于Qt的第三方库和控件
====================== 基于Qt的第三方库和控件 ====================== libQxt -------- http://dev.libqxt.o ...
- 基于存储过程的MVC开源分页控件
基于存储过程的MVC开源分页控件--LYB.NET.SPPager 摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件M ...
- Web应用程序开发,基于Ajax技术的JavaScript树形控件
感谢http://www.cnblogs.com/dgrew/p/3181769.html#undefined 在Web应用程序开发领域,基于Ajax技术的JavaScript树形控件已经被广泛使用, ...
- 基于Bootstrap仿淘宝分页控件实现
.header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...
随机推荐
- androidStudio: ERROR: Error occurred while communicating with CMake server.
遇到此错误的原因是cmake服务器协议版本不匹配: 解决方案: 1:直接更新android studio看能否解决: 2:如果解决不了,那么将androidstudio,ndk ,cmake,grad ...
- python代码-leetcode1 两数相加
1.两个循环 class Solution: def twoSum(self, nums, target): n=len(nums) for i in range(n): for j in range ...
- 机器学习 - 算法 - Xgboost 数学原理推导
工作原理 基于集成算法的多个树累加, 可以理解为是弱分类器的提升模型 公式表达 基本公式 目标函数 目标函数这里加入了损失函数计算 这里的公式是用的均方误差方式来计算 最优函数解 要对所有的样本的损失 ...
- 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_12-SpringSecurityOauth2研究-JWT研究-生成私钥和公钥
3.6.3 JWT入门 Spring Security 提供对JWT的支持,本节我们使用Spring Security 提供的JwtHelper来创建JWT令牌,校验JWT令牌 等操作. 3.6.3. ...
- Apache Commons Net中FTPClient设置成以二进制进行传输
代码: ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
- Tools - Nmap
Nmap Homepage Nmap参考指南(Man Page) Nmap中文网 wiki - Nmap 常用示例 1) Ping扫描,打印出对扫描做出响应的主机 nmap -sP 192.168.1 ...
- python获取昨日日期
获取昨日日期oneday = datetime.timedelta(days=1) 一天 day = datetime.datetime.strptime(self.date,'%Y-%m-%d') ...
- API网关从入门到放弃
前言 假设你正在开发一个电商网站,那么这里会涉及到很多后端的微服务,比如会员.商品.推荐服务等等. 那么这里就会遇到一个问题,APP/Browser怎么去访问这些后端的服务? 如果业务比较简单的话,可 ...
- sql server 日期函数
一.sql server日期时间函数Sql Server中的日期与时间函数 1. 当前系统日期.时间 select getdate() 2. dateadd 在向指定日期加上一段时间的基 ...
- websocket抓包
https://www.cnblogs.com/xiaoniuzai/p/7588739.html http://blog.sina.com.cn/s/blog_12df1b9e60102vyeq.h ...