仿海报工厂效果的自定义View

来源:互联网 发布:数据库管理系统是 编辑:程序博客网 时间:2024/05/18 01:47

今日科技快讯

昨日,乐视控股已与乐视移动全国几十家中小店建商达成了超一亿的债务偿还解决方案,剩下一小部分中小店建商也正在和他们洽谈中。有消息称,贾跃亭掌握的乐视控股与乐视移动供应商达成债务解决额超过一亿元,相关供应商还向乐视控股寄去了关于还款的感谢函,而此前在乐视大厦讨债的供应商已经离去。对此,乐视控股相关负责人予以确认。

作者简介

本篇来自 易水南风 的投稿,详细地讲解了一个仿海报工厂效果的自定义View,希望大家喜欢!

易水南风 的博客地址:

http://blog.csdn.net/sinat_23092639

效果预览

近期做了一个自定义 View,效果有些类似海报工厂,先看下效果图:

就是一个背景图,中间挖了若干个形状不同的“洞”,每个“洞”里放着一张图片,用手可以拖拽、缩放、旋转该图片,并且当前图片备操作时会有红色的高亮边框。点击选中某个图片的时候,底部会弹出菜单栏,菜单栏有三个按钮,分别是对该图片进行旋转90度、对称翻转图片、和保存整个海报到手机内置sd卡根目录。

这就类似海报工厂效果,选择若干张图片还有底部模板(就是背景图片和挖空部分的位置和形状),然后通过触摸改变选择的图片的大小位置角度,来制作一张自己喜爱的海报。

正文

这里主要是一个自定义 View,项目中叫做 JigsawView 完成的。它的基本结构是最底层绘制可操作的图片,第二层绘制背景图片,第三层绘制镂空的部分,镂空部分通过 PorterDuffXfermode 来实现,镂空部分的形状由对应手机目录的 svg 文件确定。

在用 Android 中的 Canvas 进行绘图时,可以通过使用 PorterDuffXfermode 将所绘制的图形的像素与 Canvas 中对应位置的像素按照一定规则进行混合,形成新的像素值,从而更新 Canvas 中最终的像素颜色值,这样会创建很多有趣的效果。关于 PorterDuffXfermode 详细可以参考

http://blog.csdn.net/iispring/article/details/50472485

首先这里要关掉硬件加速,因为硬件加速可能会使效果丢失。在 View 的初始化语句中调用

即可。

由于 JigsawView 的代码不少,所以这里只展示比较重要的部分,完整代码请见文章末尾的 GitHub 链接。

首先需要两支画笔:

这里图片的模型是 PictureModel 。PictureModel 主要都是包含了位置和缩放信息以及镂空部分的 HollowModel,而图片的具体位置和大小由 HollowModel 确定,图片时填充镂空部分的,以类似 ImageView 的 CenterCrop 方式填充,这个在 JigsawView 的 makePicFillHollow 方法中处理。

HollowModel 持有解析 svg 文件得到的 path 对象集合,该集合可以表示一个 svg 文件表示的路径。具体的解析工作由自定义的 SvgParseUtil 类处理,SvgParseUtil 从手机的内置 sd 卡中(当然路径可以灵活配置)读取对应的 svg 文件,然后解析为可以绘制的 Path 集合对象。SvgParseUtil 本质是解析 xml 文件(以为 svg 就是一个 xml 文件),对于 svg 路径直接拷贝系统的 PathParser 处理,其他的圆形矩形多边形就自己处理。这里具体代码这里就不展示了,详细请看 GitHub 上的源码。

以下是完整的onDraw方法:

思路还是比较清晰的。第3行到第22行为绘制可操作图片。第19行的 drawPicture 就是绘制所有的可操作图片,而当该图片对应的镂空部分没有相应的svg时,就绘制 HollowModel 的位置尺寸对应的矩形作为镂空部分,即20行的 drawPicture。

看下 drawPicture 方法:

这里主要是运用了 Matrix 处理图片的各种变化。在 onTouchEvent 方法中,会根据触摸的事件不同对正在操作的 PictureModel 对象的位置、缩放、角度进行对应的赋值,所以在 drawPicture 中将每次触摸后的赋值参数取出来,交给 Matrix 对象处理,最后通过

就能将触摸后的变化图片显示出来。 

另外第26行的 canvas.clipPath(path); 是将图片的可绘制区域限定在镂空部分中,防止图片滑动到其他的镂空区域。

注意 onDraw 的第25行的

为了正确显示 PorterDuffXfermode 所带来的的效果,需要新建一个图层,具体可以参见上面链接引用的博文。

onDraw 第26行的 drawBackGround 方法就是绘制背景,这个很简单就不必说了。

第28行到第44行为绘制镂空部分,主要是先把 HollowModel 中存储的 Path 集合取出,再通过 addPath 方法将路径数据交给 mPath 对象,再由 drawHollow 方法去真正绘制镂空部分。

这里首先对设置画笔的 PorterDuffXfermode:

这里为了镂空效果,PorterDuffXfermode 使用 PorterDuff.Mode.CLEAR。

然后对画布进行平移,然后通过 scalePathRegion 方法让表示镂空路径的 Path 对象进行缩放,使得镂空的路径填充 HollowModel 对应的矩形区域。接着使用

将镂空的路径绘制上去。

最后别忘了

恢复画布和画笔的状态。

然后 onDraw 的第47行把这个 layer 绘制到 canvas 默认的 layer 上去:

onDraw 最后的

在 onTouchEvent 中,将通过触摸事件判断哪个图片当前被选择,然后在 onDraw 中让当前被选择的图片绘制对应的 HollowModel 的边框。

onDraw 到此结束。

再看下 onTouchEvent 方法:

由于代码太长,有兴趣的朋友可以在下方阅读原文进行查看

虽然比较长,但是并不难理解,基本是比较套路化的东西,看注释应该就能懂。

总的流程就是: 

  • 首先在 Down 事件: 

  • 不管单手还是双手模式,都将选择当前点击到的图片模型,这也是为了以后的事件中可以修改选中的图片模型以在 onDraw 中改变图片的显示。

  • Move 事件中: 

  • 单手模式的话,针对每个 MOVE 事件带来的位移给 PictureModel 的位置赋值,然后就调用 invalidate 进行刷新界面。

  • 如果是双手模式,则根据每个 MOVE 事件带来的角度变化和两个手指间的距离变化分别给 PictureModel 的角度和缩放比赋值,然后调用 invalidate 进行刷新界面。

  • Up事件: 

  • 单指模式下,先判断是否已经滑动过(滑动距离小于ViewConfiguration.getTouchSlop() 就认为不是滑动而是点击),不是滑动的话就以改变当前的图片选中状态处理,切换选中状态。 是滑动过的话则取消所有图片的选中状态。

  • 双指状态下均取消所有图片的选中状态。

这里为了使得缩放旋转体验更好,所以只要手指 DOWN 事件落在镂空部分中,在没有 Up 事件的情况下即使滑出镂空部分仍然可以继续对选中的图片进行操作,避免因为镂空部分小带来的操作不便,这也和海报工厂的效果一致。

源码地址:

https://github.com/yanyinan/JigsawPoster

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

阅读全文
0 0
原创粉丝点击