• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > 8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)

8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)

作者:coder-pig 字体:[增加 减小] 来源:互联网 时间:2017-05-22

coder-pig通过本文主要向大家介绍了酷狗音乐8.3.5,酷狗8.3.5,porterduff,porterduff.mode,android porterduff等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

本节引言:

上一节,我们学习了Xfermode两个已经过世(过时)的儿子:AvoidXfermode, PixelXorXfermode, 虽然说有点用,但是终归是被淘汰的了,本节我们来学习Xfermode还健在的三儿子:PorterDuffXfermode;

先祭上官方API文档:PorterDuffXfermode!文档内容很少,我们可以看到他的构造方法:

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

这里两个图层:先绘制的图是目标图(DST),后绘制的图是源图(SRC)!

当然,在文档中我们发现可供使用的模式并不是16种,而是18种,新增了ADD和OVERLAY两种模式!

嗯,说多也白说,代码最实际,本节我们写下代码来验证下这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的Bitmap

    public 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);
        //实例化两个Bitmap
        srcBitmap = 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;
    }

    @Override
    protected 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的Xfermode
        paint.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:

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)

相关文章

  • 2017-05-26android support的作用及其常见错误的解决,androidsupport
  • 2017-05-26LVS 内核实现分析(1)
  • 2017-05-26Android中的多线程断点下载,android断点下载
  • 2017-05-26Android开发:优化ListView实践解析
  • 2017-05-26Android(Java)控制GPIO的方法及耗时分析,androidgpio
  • 2017-05-26Android adb shell命令合集
  • 2017-05-26Android音频开发(5):音频数据的编解码
  • 2017-05-26linux设备驱动程序之时钟管理(3)----我的那块儿蛋糕
  • 2017-05-26Android Studio导入Eclipse项目的两种方法,androideclipse
  • 2017-05-26Android开发学习之路--Content Provider之初体验

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Kotlin的数据类:节省很多行代码(KAD 10),kotlin很多行
    • 安卓--shape简单使用,安卓--shape
    • Android学习笔记(30):选项卡TabHost浅析
    • RK3288开发过程中遇到的问题点和解决方法之Framework,rk3288framework
    • Android中的消息通知(NotificationManager和Notification),android通知栏消息
    • 3.8 Gestures(手势)
    • 自定义Toast的显示位置和显示内容,自定义toast
    • Atitit.android播放smb 网络邻居视频文件解决方案,atitit.androidsmb
    • Android--控件属性汇总
    • Android Studio多渠道打包,androidstudio打包

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有