本节导言:

上一节,咱们学习了Xfermode两个现已过世(过期)的儿子:AvoidXfermodePixelXorXfermode, 尽管说有点用,可是终归是被筛选的了,本节咱们来学习Xfermode还健在的三儿子:PorterDuffXfermode

先祭上官方API文档:!文档内容很少,咱们能够看到他的结构办法:

参数只要一个: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的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:

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

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:

不相交的当地按原样制作源图和目标图


本节示例代码下载:


本节小结:

嗯,本节就写了一个简略的View来验证这18种不同PorterDuff.Mode下的不同作用, 嘿嘿,蛮耗时间的,不过,读者看起来必定明晰多了是吧~当然,这仅仅一些开始的见地!

PorterDuffXfermodePorterDuff.Mode关于咱们自界说控件是非常重要的! 本节咱们开始了解,下节咱们挑几个比如来练练手!

假如你想看关于PorterDuff.Mode愈加具体的介绍可见: ,他人写的不错的一篇文章! 嗯,就到这儿,明早体检,今日就写这么多~