Android基础入门教程——8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)

标签(空格分隔): Android基础入门教程


本节引言:

上一节,我们学习了Xfermode两个已经过世(过时)的儿子:AvoidXfermodePixelXorXfermode
虽然说有点用,但是终归是被淘汰的了,本节我们来学习Xfermode还健在的三儿子:PorterDuffXfermode
先祭上官方API文档:PorterDuffXfermode!文档内容很少,我们可以看到他的构造方法:

参数只有一个:PorterDuff.Mode mode,而Android给我们提供了16种图片混排模式,简单点可以
理解为两个图层按照不同模式,可以组合成不同的结果显示出来!16种混排模式的结果图如下:

这里两个图层:先绘制的图是目标图(DST),后绘制的图是源图(SRC)
当然,在文档中我们发现可供使用的模式并不是16种,而是18种,新增了ADDOVERLAY两种模式!
嗯,说多也白说,代码最实际,本节我们写下代码来验证下这18种模式吧!
PS:这个PorterDuff的命名其实是两个人名的组合:Tomas Proter和 Tom Duff组成的,他们是最早在
最早在SIGGRAPH上提出图形混合概念的大神级人物,有兴趣的自行百度~


写个例子来验证上面的这个图:

好的,我们来写个例子验证下上面这个图,通过修改不同的模式,来对结果进行对比分析!

代码实现

Step 1:我们先写个获取屏幕宽高的工具类吧!ScreenUtil.java

/*** Created by Jay on 2015/10/23 0023.*/
public class ScreenUtil {/*** 获取屏幕宽高,sdk17后不建议采用** @param context*/public static int[] getScreenHW(Context context) {WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display = manager.getDefaultDisplay();int width = display.getWidth();int height = display.getHeight();int[] HW = new int[] { width, height };return HW;}/*** 获取屏幕宽高,建议采用** @param context*/public static int[] getScreenHW2(Context context) {WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm = new DisplayMetrics();manager.getDefaultDisplay().getMetrics(dm);int width = dm.widthPixels;int height = dm.heightPixels;int[] HW = new int[] { width, height };return HW;}/*** 获取屏幕的宽度** @param context* @return*/public static int getScreenW(Context context) {return getScreenHW2(context)[0];}/*** 获取屏幕的高度** @param context* @return*/public static int getScreenH(Context context) {return getScreenHW2(context)[1];}
}

Step 2:编写我们的自定义View类,在这里做试验!XfermodeView.java

/*** Created by Jay on 2015/10/23 0023.*/
public class XfermodeView extends View {private PorterDuffXfermode pdXfermode;   //定义PorterDuffXfermode变量//定义MODE常量,等下直接改这里即可进行测试private static PorterDuff.Mode PD_MODE = PorterDuff.Mode.ADD;private int screenW, screenH; //屏幕宽高private int width = 200;      //绘制的图片宽高private int height = 200;private Bitmap srcBitmap, dstBitmap;     //上层SRC的Bitmap和下层Dst的Bitmappublic XfermodeView(Context context) {this(context, null);}public XfermodeView(Context context, AttributeSet attrs) {super(context, attrs);screenW = ScreenUtil.getScreenW(context);screenH = ScreenUtil.getScreenH(context);//创建一个PorterDuffXfermode对象pdXfermode = new PorterDuffXfermode(PD_MODE);//实例化两个BitmapsrcBitmap = makeSrc(width, height);dstBitmap = makeDst(width, height);}public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}//定义一个绘制圆形Bitmap的方法private Bitmap makeDst(int w, int h) {Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bm);Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(0xFF26AAD1);c.drawOval(new RectF(0, 0, w * 3 / 4, h * 3 / 4), p);return bm;}//定义一个绘制矩形的Bitmap的方法private Bitmap makeSrc(int w, int h) {Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(bm);Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);p.setColor(0xFFFFCE43);c.drawRect(w / 3, h / 3, w * 19 / 20, h * 19 / 20, p);return bm;}@Overrideprotected void onDraw(Canvas canvas) {Paint paint = new Paint();paint.setFilterBitmap(false);paint.setStyle(Paint.Style.FILL);canvas.drawBitmap(srcBitmap, (screenW / 3 - width) / 2, (screenH / 2 - height) / 2, paint);canvas.drawBitmap(dstBitmap, (screenW / 3 - width) / 2 + screenW / 3, (screenH / 2 - height) / 2, paint);//创建一个图层,在图层上演示图形混合后的效果int sc = canvas.saveLayer(0, 0, screenW, screenH, null, Canvas.MATRIX_SAVE_FLAG |Canvas.CLIP_SAVE_FLAG |Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |Canvas.FULL_COLOR_LAYER_SAVE_FLAG |Canvas.CLIP_TO_LAYER_SAVE_FLAG);canvas.drawBitmap(dstBitmap, (screenW / 3 - width) / 2 + screenW / 3 * 2,(screenH / 2 - height) / 2, paint);     //绘制i//设置Paint的Xfermodepaint.setXfermode(pdXfermode);canvas.drawBitmap(srcBitmap, (screenW / 3 - width) / 2 + screenW / 3 * 2,(screenH / 2 - height) / 2, paint);paint.setXfermode(null);// 还原画布canvas.restoreToCount(sc);}
}

代码看起来好复杂是吧,其实不然,无非就是获取了屏幕宽高,然后画了一个矩形一个圆形,
计算了一下他们的位置,然后设置下图层(固定写法),接着设下下画笔setXfermode,接着
绘制到canvas上而已,你看不懂的可能是绘制位置的计算吧,其实不然,位置你喜欢怎么定
都可以!那么接下来我们来一个个看下解果咯,你只需修改PD_MODE的值设置为不同模式即可!

运行效果图

1)PorterDuff.Mode.ADD:

饱和度叠加

2)PorterDuff.Mode.CLEAR:

所绘制不会提交到画布上,嗯结果…不知道是为什么了,正常是没东西的..

3)PorterDuff.Mode.DARKEN:

取两图层全部区域,交集部分颜色加深

4)PorterDuff.Mode.DST:

只保留目标图的alpha和color,所以绘制出来只有目标图

5)PorterDuff.Mode.DST_ATOP:

源图和目标图相交处绘制目标图,不相交的地方绘制源图

6)PorterDuff.Mode.DST_IN:

两者相交的地方绘制目标图,绘制的效果会受到原图处的透明度影响

7)PorterDuff.Mode.DST_OUT:

在不相交的地方绘制目标图

8)PorterDuff.Mode.DST_OVER:

目标图绘制在上方

9)PorterDuff.Mode.LIGHTEN:

取两图层全部区域,点亮交集部分颜色

10)PorterDuff.Mode.MULTIPLY:

取两图层交集部分叠加后颜色

11)PorterDuff.Mode.OVERLAY:

叠加

12)PorterDuff.Mode.SCREEN:

取两图层全部区域,交集部分变为透明色

13)PorterDuff.Mode.SRC:

只保留源图像的alpha和color,所以绘制出来只有源图

14)PorterDuff.Mode.SRC_ATOP:

源图和目标图相交处绘制源图,不相交的地方绘制目标图

15)PorterDuff.Mode.SRC_IN:

两者相交的地方绘制源图

16)PorterDuff.Mode.SRC_OUT:

不相交的地方绘制源图

17)PorterDuff.Mode.SRC_OVER:

把源图绘制在上方

18)PorterDuff.Mode.XOR:

不相交的地方按原样绘制源图和目标图


本节示例代码下载:

PorterDuffXfermodeDemo.zip


本节小结:

嗯,本节就写了一个简单的View来验证这18种不同PorterDuff.Mode下的不同效果,
嘿嘿,蛮耗时间的,不过,读者看起来肯定清晰多了是吧~当然,这只是一些初步的见解!
PorterDuffXfermodePorterDuff.Mode对于我们自定义控件是非常重要的!
本节我们初步了解,下节我们挑几个例子来练练手!
如果你想看关于PorterDuff.Mode更加详细的介绍可见:
Android Paint之 setXfermode PorterDuffXfermode 讲解,别人写的不错的一篇文章!
嗯,就到这里,明早体检,今天就写这么多~

Android基础入门教程——8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)相关推荐

  1. Android基础入门教程——8.3.13 Paint API之—— Shader(图像渲染)

    Android基础入门教程--8.3.13 Paint API之-- Shader(图像渲染) 标签(空格分隔): Android基础入门教程 本节引言: 最近一段时间因为工作上的事以及面试等等,耽误 ...

  2. Android基础入门教程——8.3.14 Paint几个枚举-常量值以及ShadowLayer阴影效果

    Android基础入门教程--8.3.14 Paint几个枚举/常量值以及ShadowLayer阴影效果 标签(空格分隔): Android基础入门教程 本节引言: 在Android基础入门教程--8 ...

  3. Android基础入门教程——8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash

    Android基础入门教程--8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash 标签(空格分隔): Android基础入门教程 本节引言: 在Canva ...

  4. 最新Android基础入门教程目录(完结版)

    第一章:环境搭建与开发相关(已完结 10/10) https://blog.csdn.net/coder_pig/article/details/50000773 Android基础入门教程--1.1 ...

  5. 2015年最新Android基础入门教程目录(完结版)

    2015年最新Android基础入门教程目录(完结版) 标签(空格分隔): Android基础入门教程 前言: 关于<2015年最新Android基础入门教程目录>终于在今天落下了帷幕,全 ...

  6. Android基础入门教程——8.3.1 三个绘图工具类详解

    Android基础入门教程--8.3.1 三个绘图工具类详解 标签(空格分隔): Android基础入门教程 本节引言: 上两小节我们学习了Drawable以及Bitmap,都是加载好图片的,而本节我 ...

  7. android 编辑9图片,Android基础入门教程——1.6 .9(九妹)图片怎么玩

    Android基础入门教程--1.6 .9(九妹)图片怎么玩 Android基础入门教程 1.本节引言: 可能有的一些疑问: 1.什么是.9图片? 答:图片后缀名前有.9的图片,如pic1.9.png ...

  8. android设置webview缓存目录,Android基础入门教程——7.5.5 WebView缓存问题

    Android基础入门教程--7.5.5 WebView缓存问题 Android基础入门教程 本节引言:现在很多门户类信息网站,比如虎嗅,ifanr,钛媒体等等的APP,简单点说是信息阅读类的APP, ...

  9. Android基础入门教程——4.3.1 BroadcastReceiver牛刀小试

    Android基础入门教程--4.3.1 BroadcastReceiver牛刀小试 标签(空格分隔): Android基础入门教程 本节引言 本节我们将来学习Android四大组件中的第三个:Bro ...

最新文章

  1. hibernate.hbm2ddl.auto的value
  2. Android性能优化之运算篇
  3. linux rqm包制作 spec文件详解
  4. 【控制】《多智能体系统的协同群集运动控制》陈杰老师-第4章-连通性保持下多移动机器人群集控制
  5. PMCAFF微课堂|简书大咖彭小六:6年PM是如何利用阅读进行职场提升
  6. 永冻土层matlab图片,俄永冻土层现冰河期洞熊,站立可达3.5米,身体各器官保存完好...
  7. 【MFC】对话框中创建工具栏
  8. ubuntu下gcc的安装与使用
  9. javascript --- 类、class、事件委托的编程风格
  10. 张文宏又爆“金句”:上班开会,要和关系最差的人坐一起……
  11. 通过日志恢复oracle序列,(存档日志包含序列84,要求序列36)怎么恢复啊?
  12. Docker-Compose快速搭建Oracle-11G系统
  13. python3.7 keras和tensorflow兼容_解决Keras 与 Tensorflow 版本之间的兼容性问题
  14. Win7性能优化:解决多核处理器兼容问题
  15. 软件架构--《企业IT架构转型之道》笔记
  16. 数据线性拟合优化之路
  17. 一位退市天才呕心沥血悟出的均线法则,句句经典
  18. 【转载】电磁波中的波段划分:L波段、S波段、C波段、X波段、Ku波段、K波段、Ka波段 等等
  19. android 无线传递文件夹,android 通过WIFI实现文件传输
  20. Ubuntu 12.04 常用三种输入法及键盘错乱的调整

热门文章

  1. 【阅读3.8w,收藏2000次】97页《Python自动化办公文档》,让您的 “办公效率” 提高100倍,拿走即用!
  2. Redis实战 - 09 Redis BitMaps 实现用户签到,统计签到次数,统计签到情况等功能
  3. 2008年1月8日,完美时空首部战争史诗大作《赤壁》将开启正式内测。
  4. 2020-12-21 数学基础 -- 序列极限(夹逼定理、重要极限、聚点原理)
  5. Android MVC框架
  6. [C] 三、回调结构体
  7. 互联互通,区块链的跨链方式
  8. 博杰声学测试软件,半消声室设计
  9. 如何用课件制作工具制作三角形旋转动画
  10. python死循环用什么好弄_是什么神药,治好了我的Python循环语句恐惧症?!