一、概述

Xfermode全名transfer-mode,其作用是实现两张图叠加时的混合效果。

网上流传的关于Xfermode最出名的图来源于AndroidSDK的samples中,名叫Xfermodes.java,效果如下:

二、体验

提炼出Xfermodes.java中的核心代码,自己写了个简单粗暴的demo试试水:

 public class ImageViewXfermode extends ImageView {
public ImageViewXfermode(Context context) {
super(context);
init();
} public ImageViewXfermode(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} public ImageViewXfermode(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
} private void init() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
} @Override
protected void onDraw(Canvas canvas) {
int defaultWidth = dip2px(85); //xml里view的宽度是85dp
int defaultdHeight = dip2px(85); //xml里view的高度是85dp if (canvas.getHeight() == defaultWidth && canvas.getHeight() == defaultdHeight) {
//拿到黄色圆形的bitmap
Bitmap bitcircle = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvascicle = new Canvas(bitcircle);
Paint paintcicle = new Paint(Paint.ANTI_ALIAS_FLAG);
paintcicle.setColor(0xFFFFCC44);
canvascicle.drawCircle(dip2px(30), dip2px(30), dip2px(25), paintcicle); //拿到蓝色矩形的bitmap
Bitmap bitrect = Bitmap.createBitmap(defaultWidth, defaultdHeight, Config.ARGB_8888);
Canvas canvasrect = new Canvas(bitrect);
Paint paintrect = new Paint(Paint.ANTI_ALIAS_FLAG);
paintrect.setColor(0xFF66AAFF);
canvasrect.drawRect(dip2px(30), dip2px(30), dip2px(80), dip2px(80), paintrect); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Xfermode xfermode = new PorterDuffXfermode(Mode.LIGHTEN); //采用saveLayer,让后续canvas的绘制在自动创建的bitmap上
int cnt = canvas.saveLayer(0, 0, defaultWidth, defaultdHeight, null, Canvas.ALL_SAVE_FLAG);
//先画圆形,圆形是dest
canvas.drawBitmap(bitcircle, 0, 0, paint);
paint.setXfermode(xfermode);
//后画矩形,矩形是src
canvas.drawBitmap(bitrect, 0, 0, paint);
paint.setXfermode(null);
canvas.restoreToCount(cnt);
} else {
super.onDraw(canvas);
}
} private int dip2px(float dip) {
float scale = getResources().getDisplayMetrics().density;
return (int)(dip * scale + 0.5f);
}
}

效果如下:

介绍一下几个关键点:

1、关于src和dest

  先绘制到canvas上的是dest,后绘制的是src

2、关于硬件加速

  在sdkversion>=11时,需要关闭硬件加速(第19行),否则 Mode.CLEAR 、 Mode.DARKEN 、 Mode.LIGHTEN 三种模式下绘制效果不正常

3、saveLayer的作用

  Canvas.saveLayer在Canvas.save的基础上,额外自动分配了一个bitmap,使得saveLayer之后的所有绘制都在这个新分配的bitmap上完成。

  如果把saveLayer去掉呢?效果就是蓝色矩形跟黄色圆形和灰色背景都进行了 Mode.LIGHTEN 操作:

  

4、如果不saveLayer

  有一种变通的方法,在dest对应bitmap的canvas上绘制src对应的bitmap,这样的目的与saveLayer是一致的,不在当前canvas上直接绘图:

     @Override
protected void onDraw(Canvas canvas) {
int defaultWidth = dip2px(85); //xml里view的宽度是85dp
int defaultdHeight = dip2px(85); //xml里view的高度是85dp if (canvas.getHeight() == defaultWidth && canvas.getHeight() == defaultdHeight) {
//拿到黄色圆形的bitmap
Bitmap bitcircle = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvascicle = new Canvas(bitcircle);
Paint paintcicle = new Paint(Paint.ANTI_ALIAS_FLAG);
paintcicle.setColor(0xFFFFCC44);
canvascicle.drawCircle(dip2px(30), dip2px(30), dip2px(25), paintcicle); //拿到蓝色矩形的bitmap
Bitmap bitrect = Bitmap.createBitmap(defaultWidth, defaultdHeight, Config.ARGB_8888);
Canvas canvasrect = new Canvas(bitrect);
Paint paintrect = new Paint(Paint.ANTI_ALIAS_FLAG);
paintrect.setColor(0xFF66AAFF);
canvasrect.drawRect(dip2px(30), dip2px(30), dip2px(80), dip2px(80), paintrect); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Xfermode xfermode = new PorterDuffXfermode(Mode.LIGHTEN); //设置setXfermode
paint.setXfermode(xfermode);
//在圆形的canvas上画矩形,先画圆形,圆形是dest,后画矩形,矩形是src
canvascicle.drawBitmap(bitrect, 0, 0, paint);
paint.setXfermode(null);
//将圆形canvas上画出来的结果绘制到canvas上
canvas.drawBitmap(bitcircle, 0.0f, 0.0f, paint);
} else {
super.onDraw(canvas);
}
}

[转载请保留本文地址:http://www.cnblogs.com/goagent/p/5326438.html] 

三、更多玩法——圆形ImageView

利用Xfermode的特性也可以做出圆形的ImageView来。先画原图,再画圆形,采用 Mode.DST_IN 即可:

     @Override
protected void onDraw(Canvas canvas) {
int defaultWidth = dip2px(85); //xml里view的宽度是85dp
int defaultdHeight = dip2px(85); //xml里view的高度是85dp
Drawable drawable = getDrawable(); if (canvas.getHeight() == defaultWidth && canvas.getHeight() == defaultdHeight && drawable instanceof BitmapDrawable) {
//setBackgroundColor(Color.TRANSPARENT);
//拿到原图的bitmap
Bitmap bitimg = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvasimg = new Canvas(bitimg);
Matrix matrix = new Matrix();
matrix.setScale(defaultWidth * 1.0f / drawable.getIntrinsicWidth(), defaultdHeight * 1.0f / drawable.getIntrinsicHeight());
Paint paintimg = new Paint(Paint.ANTI_ALIAS_FLAG);
canvasimg.drawBitmap(((BitmapDrawable)drawable).getBitmap(), matrix, paintimg); //拿到圆形的bitmap
Bitmap bitcircle = Bitmap.createBitmap(defaultWidth, defaultdHeight, Config.ARGB_8888);
Canvas canvascircle = new Canvas(bitcircle);
Paint paintcircle = new Paint(Paint.ANTI_ALIAS_FLAG);
paintcircle.setColor(0xFF66AAFF);
canvascircle.drawCircle(dip2px(85 / 2.0f), dip2px(85 / 2.0f), dip2px(85 / 2.0f), paintcircle); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Xfermode xfermode = new PorterDuffXfermode(Mode.DST_IN); //采用saveLayer,让后续canvas的绘制在自动创建的bitmap上
int cnt = canvas.saveLayer(0, 0, defaultWidth, defaultdHeight, null, Canvas.ALL_SAVE_FLAG);
//先画原图,原图是dest
canvas.drawBitmap(bitimg, 0, 0, paint);
paint.setXfermode(xfermode);
//后画圆形,圆形是src
canvas.drawBitmap(bitcircle, 0, 0, paint);
paint.setXfermode(null);
canvas.restoreToCount(cnt);
} else {
super.onDraw(canvas);
}
}

[转载请保留本文地址:http://www.cnblogs.com/goagent/p/5326438.html] 

Android Xfermode 学习笔记的更多相关文章

  1. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  2. Android自动化学习笔记之MonkeyRunner:官方介绍和简单实例

    ---------------------------------------------------------------------------------------------------- ...

  3. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

  4. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  5. Android 数字签名学习笔记

    Android 数字签名学习笔记 在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个permission的pro ...

  6. Android:日常学习笔记(9)———探究持久化技术

    Android:日常学习笔记(9)———探究持久化技术 引入持久化技术 什么是持久化技术 持久化技术就是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失 ...

  7. Android:日常学习笔记(9)———探究广播机制

    Android:日常学习笔记(9)———探究广播机制 引入广播机制 Andorid广播机制 广播是任何应用均可接收的消息.系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播.通过将 In ...

  8. Android:日常学习笔记(8)———开发微信聊天界面

    Android:日常学习笔记(8)———开发微信聊天界面 只做Nine-Patch图片 Nine-Patch是一种被特殊处理过的PNG图片,能够指定哪些区域可以被拉升,哪些区域不可以.

  9. Android:日常学习笔记(8)———探究UI开发(5)

    Android:日常学习笔记(8)———探究UI开发(5) ListView控件的使用 ListView概述 A view that shows items in a vertically scrol ...

随机推荐

  1. 一年之计在于春,2015开篇:PDF.NET SOD Ver 5.1完全开源

    前言: 自从我2014年下半年到现在的某电商公司工作后,工作太忙,一直没有写过一篇博客,甚至连14年股票市场的牛市都错过了,现在马上要过年了,而今天又是立春节气,如果再不动手,那么明年这个无春的年,也 ...

  2. Centos 6.6 下搭建php5.2.17+Zend Optimizer3.3.9+Jexus环境

    (为何安装php5.2.17这个版本 因为phpweb这个程序用到了Zend Optimizer3.3.9 这个东东已经停止更新了 最高支持5.2版本的php 所以就有了一晚上填坑的自己和总结了这篇文 ...

  3. Asp.Net 5 新增公告仓库

    一直以来Asp.Net 5 都没有一个比较统一的公告页,对于一个在日夜更新的项目来说,很多人经常会遇到问题但是不知道去哪里寻找帮助,现在Asp.Net 5 项目组新增了一个公告仓库来解决这个问题.  ...

  4. [模拟电路] 2、Passive Band Pass Filter

    note: Some articles are very good in http://www.electronics-tutorials.ws/,I share them in the Cnblog ...

  5. 升级xcode8 之后遇到的一些问题

    昨天趁着快下班,就将xcode升级为8了,运行起来并没有什么问题,今天一早过来运行,结果,模拟器打不开了.... 1. unable to boot the Simulator 解决办法:重启Mac时 ...

  6. SQL Server 多实例下的复制

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 搭建步骤(Procedure) 注意事项(Attention) 二.背景(Contexts) ...

  7. JavaScript权威设计--JavaScript变量,作用域,声明提前(简要学习笔记四)

    1.宿主对象与宿主环境 宿主对象:由ECMAScript实现的宿主环境提供的对象,可以理解为:浏览器提供的对象.所有的BOM和DOM都是宿主对象.   宿主环境:一般宿主环境由外壳程序创建与维护,只要 ...

  8. Git 常用命令

    一.初始環境配置 git config --global user.name "John Doe"git config --global user.email johndoe@ex ...

  9. 【基于WinForm+Access局域网共享数据库的项目总结】之篇三:Access远程连接数据库和窗体打包部署

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  10. Java 素数 prime numbers-LeetCode 204

    Description: Count the number of prime numbers less than a non-negative number, n click to show more ...