android Xfermode PorterDuffXfermode 实现遮罩层

参考:

http://www.cnblogs.com/jacktu/archive/2012/01/02/2310326.html

http://blog.csdn.net/yun90/article/details/8618521

 

基础知识:

1.下面的Xfermode子类可以改变这种行为:

AvoidXfermode  指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。

PixelXorXfermode  当覆盖已有的颜色时,应用一个简单的像素XOR操作。

PorterDuffXfermode  这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。

要应用转换模式,可以使用setXferMode方法,如下所示:

AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID);    borderPen.setXfermode(avoid);

 

2.Porter-Duff 效果图:

 

3.16条Porter-Duff规则

1.PorterDuff.Mode.CLEAR

   所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC

   显示上层绘制图片
3.PorterDuff.Mode.DST

  显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER

  正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER

  上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN

   取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN

  取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT

 取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT

 取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP

 取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP

  取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR

  
13.PorterDuff.Mode.DARKEN


14.PorterDuff.Mode.LIGHTEN


15.PorterDuff.Mode.MULTIPLY


16.PorterDuff.Mode.SCREEN

实例1:

首先用图片处理软件制作一个和中间黄色区域相同的图形,我们将在代码中设置它做为遮罩。

 mast 图

View的draw方法

 

public void draw(Canvas canvas) {  
        //背景部分,也就是上面的图形  
        Bitmap background = BitmapFactory.decodeResource(getResources(),  
                R.drawable.guage);  
        //遮罩,就是提取来部分  
        Bitmap mask = BitmapFactory.decodeResource(getResources(),  
                R.drawable.mask);  
          
        canvas.drawColor(Color.WHITE);  
        canvas.drawBitmap(background, 0, 0, null);  
        Paint paint = new Paint();  
        paint.setFilterBitmap(false);  
  
        int x = 0;  
        int y = 0;  
  
        // draw the src/dst example into our offscreen bitmap  
        int sc = canvas.saveLayer(x, y, x + background.getWidth(), y + background.getHeight(), 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(mDstB, 0, 0, paint);  
        canvas.drawRect(0, 0, background.getWidth() / 2, background  
                .getHeight(), paint);  
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));  
        // canvas.drawBitmap(mSrcB, 0, 0, paint);  
        canvas.drawBitmap(mask, 0f, 0f, paint);  
        paint.setXfermode(null);  
        canvas.restoreToCount(sc);  
  
    }  

 

 

只用控制绘制的矩形的长度就可以实现进度条的效果了。


             

实例2

launcher程序中将icon设置为圆角形状

package com.example.testsurfaceview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

@SuppressLint("NewApi")
public class CustomSurfaceView extends SurfaceView implements Callback {

    public CustomSurfaceView(Context context, AttributeSet attrs,
            int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    public CustomSurfaceView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public CustomSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomSurfaceView(Context context) {
        super(context);
        init();
    }

    private void init() {
        this.getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Canvas canvas = getHolder().lockCanvas();
        canvas.drawColor(Color.WHITE);

        int w = canvas.getWidth();
        int h = canvas.getHeight();

        Bitmap bitmap = this.getIcon(this.getContext());
        
        Bitmap mat = BitmapFactory.decodeResource(this.getResources(), R.drawable.default_icon_mask);

        bitmap = this.composeMat(this.getContext(), bitmap, mat);
        
        int left = (w - bitmap.getWidth()) / 2;
        int top = (h - bitmap.getHeight()) / 2;

        canvas.drawBitmap(bitmap, left, top, new Paint());

        getHolder().unlockCanvasAndPost(canvas);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub

    }

    private Bitmap getIcon(Context mContext) {
        int wh = (int) mContext.getResources().getDimension(R.dimen.icon_wh);
        int width = wh;
        int height = wh;
        Drawable icon = mContext.getResources().getDrawable(
                R.drawable.ic_launcher);

        if (icon instanceof PaintDrawable) {
            PaintDrawable painter = (PaintDrawable) icon;
            painter.setIntrinsicWidth(width);
            painter.setIntrinsicHeight(height);
        } else if (icon instanceof BitmapDrawable) {
            // Ensure the bitmap has a density.
            BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
            Bitmap bitmap = bitmapDrawable.getBitmap();
            if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
                bitmapDrawable.setTargetDensity(mContext.getResources()
                        .getDisplayMetrics());
            }
        }
        int sourceWidth = icon.getIntrinsicWidth();
        int sourceHeight = icon.getIntrinsicHeight();

        if (sourceWidth > 0 && sourceHeight > 0) {
            // There are intrinsic sizes.
            if (wh < sourceWidth || wh < sourceHeight) {
                // It's too big, scale it down.
                final float ratio = (float) sourceWidth / sourceHeight;
                if (sourceWidth > sourceHeight) {
                    height = (int) (width / ratio);
                } else if (sourceHeight > sourceWidth) {
                    width = (int) (height * ratio);
                }
            } else if (sourceWidth < width && sourceHeight < height) {
                // Don't scale up the icon
                width = sourceWidth;
                height = sourceHeight;
            }
        }
        int textureWidth = wh;
        int textureHeight = wh;
        final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
                Bitmap.Config.ARGB_8888);
        Canvas sCanvas = new Canvas();
        sCanvas.setBitmap(bitmap);
        sCanvas.drawColor(Color.GRAY);

        final int left = (textureWidth - width) / 2;
        final int top = (textureHeight - height) / 2;
        icon.setBounds(left, top, left + width, top + height);

        Rect sOldBounds = new Rect();
        sOldBounds.set(icon.getBounds());
        icon.setBounds(left, top, left + width, top + height);
        icon.draw(sCanvas);
        icon.setBounds(sOldBounds);
        sCanvas.setBitmap(null);

        return bitmap;
    }

    private static final Paint sThemePaint2 = new Paint();
    private static final android.graphics.Xfermode Xfermode_DST_IN = new PorterDuffXfermode(
            Mode.DST_IN);
    private static final android.graphics.Xfermode Xfermode_SRC_IN = new PorterDuffXfermode(
            Mode.SRC_IN);

    private Bitmap composeMat(Context context, Bitmap src, Bitmap mat) {
        int sIconWidth = mat.getWidth();
        int sIconHeight = mat.getHeight();
        final Bitmap base = Bitmap.createBitmap(sIconWidth, sIconHeight,
                Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(base);
        sThemePaint2.setXfermode(null);
//        canvas.drawRect(new Rect(0, 0, sIconWidth, sIconHeight), sThemePaint2);
//        sThemePaint2.setXfermode(Xfermode_SRC_IN);
        canvas.drawBitmap(mat, (sIconWidth-mat.getWidth())/2, (sIconHeight-mat.getHeight())/2, sThemePaint2);
        sThemePaint2.setXfermode(Xfermode_SRC_IN);        
        canvas.drawBitmap(src, ((sIconWidth-src.getWidth())/2), (sIconHeight-src.getHeight())/2, sThemePaint2);
        sThemePaint2.setXfermode(null);

        return base;
    }

}

 

posted on 2015-03-17 18:56  wjw334  阅读(999)  评论(0编辑  收藏  举报

导航