常见的图片裁剪有两种,一种是图片固定,裁剪框移动放缩来确定裁剪区域,早期见的比较多,缺点在于不能直接预览裁剪后的效果;还有一种现在比较普遍了,就是裁剪框固定,直接拖动缩放图片,便于预览裁剪结果。

我做的这个控件属于后者。一般来说,做图片裁剪的思路无外乎是先监听手势,获取坐标,再对图片变形,最后确定裁剪区域的坐标对位图进行裁剪,最后保存图片到本地。我嘛还是个技术小白,一想到要监控手势这些就头疼,碰巧项目之前为了做查看大图而引入了大名鼎鼎的第三方图片查看控件——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的头像/圆形裁剪控件的更多相关文章

  1. Android开发技巧——定制仿微信图片裁剪控件

    拍照--裁剪,或者是选择图片--裁剪,是我们设置头像或上传图片时经常需要的一组操作.上篇讲了Camera的使用,这篇讲一下我对图片裁剪的实现. 背景 下面的需求都来自产品. 裁剪图片要像微信那样,拖动 ...

  2. [UWP]如何实现UWP平台最佳图片裁剪控件

    前几天我写了一个UWP图片裁剪控件ImageCropper(开源地址),自认为算是现阶段UWP社区里最好用的图片裁剪控件了,今天就来分享下我编码的过程. 为什么又要造轮子 因为开发需要,我们需要使用一 ...

  3. 基于存储过程的MVC开源分页控件--LYB.NET.SPPager

    摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件MVCPager(http://www.webdiyer.com/)算 ...

  4. FineUI 基于 ExtJS 的专业 ASP.NET 控件库

    FineUI 基于 ExtJS 的专业 ASP.NET 控件库 http://www.fineui.com/

  5. 基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串、list集合(MVC5)<二>

    上篇博客给大家介绍了基于Bootstrap的JQuery TreeView树形控件,数据支持json字符串.list集合(MVC5)<一>, 其中的两种方式都显得有些冗余.接着上篇博客继续 ...

  6. 基于Qt的第三方库和控件

    ====================== 基于Qt的第三方库和控件 ======================     libQxt --------   http://dev.libqxt.o ...

  7. 基于存储过程的MVC开源分页控件

    基于存储过程的MVC开源分页控件--LYB.NET.SPPager 摘要 现在基于ASP.NET MVC的分页控件我想大家都不陌生了,百度一下一大箩筐.其中有不少精品,陕北吴旗娃杨涛大哥做的分页控件M ...

  8. Web应用程序开发,基于Ajax技术的JavaScript树形控件

    感谢http://www.cnblogs.com/dgrew/p/3181769.html#undefined 在Web应用程序开发领域,基于Ajax技术的JavaScript树形控件已经被广泛使用, ...

  9. 基于Bootstrap仿淘宝分页控件实现

    .header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...

随机推荐

  1. MediaPlayer: MediaPlayer中的prepare方法和prepareAsync方法的区别

    prepare方法是将资源同步缓存到内存中,一般加载本地较小的资源可以用这个,如果是较大的资源或者网络资源建议使用prepareAsync方法,异步加载.但如果想让资源启动,即start()起来,因为 ...

  2. springboot之freemarker 和thymeleaf模板web开发

    Spring Boot 推荐使用Thymeleaf.FreeMarker.Velocity.Groovy.Mustache等模板引擎.不建议使用JSP. 一.Spring Boot 中使用Thymel ...

  3. GPS nmealib学习 问题

    When building on Ubuntu 12.x the build fails with the following error… gcc  samples/generate/main.o ...

  4. java如何压缩多个文件到压缩包,并下载到浏览器?

    java压缩多个文件到压缩包,并下载到浏览器   解决方法: 完整的方法如下,很简单,亲试有效,极力推荐. 我是以流作为文件,而不是file,循环把所有pdf文件压缩到pdf.zip压缩包中. 1.前 ...

  5. QML访问C++类内部

    0.前提 C++类需要继承QObject,且有Q_OBJECT宏[所以QT自己的那么多类按道理上QML都是可以直接访问的,nb] 1.QML访问C++中的非private槽函数 可直接调用 信号也是 ...

  6. PAT 甲级 1032 Sharing (25 分)(结构体模拟链表,结构体的赋值是深拷贝)

    1032 Sharing (25 分)   To store English words, one method is to use linked lists and store a word let ...

  7. 第十二章 与Spring集成——《跟我学Shiro》

    转发:https://www.iteye.com/blog/jinnianshilongnian-2029717 目录贴:跟我学Shiro目录贴 Shiro的组件都是JavaBean/POJO式的组件 ...

  8. iOS- Core Foundation对象与OC对象相对转换

    对ARC盲目依赖的同学: 1过度使用block后,无法解决循环引用问题 2遇到底层Core Foundation对象,需要自己手工管理它们的引用计数时,显得一筹莫展 first:对于底层Core Fo ...

  9. CentOS 7 vi常用命令

    用vi打开一个yum文件 vi /usr/bin/yum 按 i 键后  进入insert模式,进入insert模式后才能进行修改 修改完成后 按esc键进入command模式, 然后:wq 保存文件 ...

  10. CentOS 7 命令

    常用命令 文件与目录操作 命令 解析 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd - 返回上次所在目录 cp file1 file ...