`
aliusa
  • 浏览: 82340 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

利用PorterDuff.Mode做橡皮擦效果

阅读更多
http://stackoverflow.com/questions/3467334/erase-bitmap-parts-using-porterduff-mode
假如我有一张背景图片,
在背景图片上覆盖绘制了一层半透明的绿色
当我们用手指涂抹屏幕的时候,手指涂抹过的地方绿色就被擦除,露出下面原先被遮挡住的背景图片
1.利用canvas的drawPath做擦除效果。
效果如下:



实现代码:
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

public class Eraser_Use_drawPath extends Activity {

    private int SCREEN_W;

    private int SCREEN_H;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));

    }

    class MyView extends View {
        private Bitmap mBitmap;
        private Canvas mCanvas;
        private Paint mPaint;
        private Path  mPath;
        private float mX, mY;
        private static final float TOUCH_TOLERANCE = 4;
        
        public MyView(Context context) {
            super(context);
            setFocusable(true);
            setScreenWH();
            setBackGround();
            
            // 1.if cover is a image,you can open MENU_ITEM_COMMENT bellow
            //Bitmap bm = createBitmapFromSRC();
            // if you want to set cover image's alpha,you can open MENU_ITEM_COMMENT bellow
            //bm = setBitmapAlpha(bm, 100);
            // if you want to scale cover image,you can open MENU_ITEM_COMMENT bellow
            //bm = scaleBitmapFillScreen(bm);

            // 2.if cover is color
            Bitmap bm = createBitmapFromARGB(0x8800ff00, SCREEN_W, SCREEN_H);
            setCoverBitmap(bm);

        }

        private void setScreenWH() {
            // get screen info
            DisplayMetrics dm = new DisplayMetrics();
            dm = this.getResources().getDisplayMetrics();
            // get screen width
            int screenWidth = dm.widthPixels;
            // get screen height
            int screenHeight = dm.heightPixels;

            SCREEN_W = screenWidth;
            SCREEN_H = screenHeight;
        }

        private Bitmap createBitmapFromSRC() {
            return BitmapFactory.decodeResource(getResources(),
                                                R.drawable.cover);
        }

        /**
         * 
         * @param colorARGB should like 0x8800ff00
         * @param width
         * @param height
         * @return
         */
        private Bitmap createBitmapFromARGB(int colorARGB, int width, int height) {
            int[] argb = new int[width * height];

            for (int i = 0; i < argb.length; i++) {

                argb[i] = colorARGB;

            }
            return Bitmap.createBitmap(argb, width, height, Config.ARGB_8888);
        }

        /**
         * 
         * @param bm
         * @param alpha ,and alpha should be like ox00000000-oxff000000
         * @note set bitmap's alpha
         * @return
         */
       /* private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());


            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }*/
        
        /**
         * 
         * @param bm
         * @param alpha ,alpha should be between 0 and 255
         * @note set bitmap's alpha
         * @return
         */
        private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());

            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha << 24) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }
        
        /**
         * 
         * @param bm
         * @note if bitmap is smaller than screen, you can scale it fill the screen.
         * @return 
         */
        private Bitmap scaleBitmapFillScreen(Bitmap bm) {
            return Bitmap.createScaledBitmap(bm, SCREEN_W, SCREEN_H, true);
        }

        
        private void setBackGround() {
            setBackgroundResource(R.drawable.background);
        }

        /**
         * 
         * @param bm
         * @note set cover bitmap , which  overlay on background. 
         */
        private void setCoverBitmap(Bitmap bm) {
            // setting paint
            mPaint = new Paint();
            mPaint.setAlpha(0);
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mPaint.setAntiAlias(true);
            
            mPaint.setDither(true);
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeJoin(Paint.Join.ROUND);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            mPaint.setStrokeWidth(20);
            
            //set path
            mPath =  new Path();;

            // converting bitmap into mutable bitmap
            mBitmap = Bitmap.createBitmap(SCREEN_W, SCREEN_H, Config.ARGB_8888);
            mCanvas = new Canvas();
            mCanvas.setBitmap(mBitmap);
            // drawXY will result on that Bitmap
            // be sure parameter is bm, not mBitmap
            mCanvas.drawBitmap(bm, 0, 0, null);
        }

       

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(mBitmap, 0, 0, null);
            mCanvas.drawPath(mPath, mPaint);
            super.onDraw(canvas);
        }
        
        private void touch_start(float x, float y) {
            mPath.reset();
            mPath.moveTo(x, y);
            mX = x;
            mY = y;
        }
        private void touch_move(float x, float y) {
            float dx = Math.abs(x - mX);
            float dy = Math.abs(y - mY);
            if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
                mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
                mX = x;
                mY = y;
            }
        }
        private void touch_up() {
            mPath.lineTo(mX, mY);
            // commit the path to our offscreen
            mCanvas.drawPath(mPath, mPaint);
            // kill this so we don't double draw
            mPath.reset();
        }
        
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touch_start(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_MOVE:
                    touch_move(x, y);
                    invalidate();
                    break;
                case MotionEvent.ACTION_UP:
                    touch_up();
                    invalidate();
                    break;
            }
            return true;
        }
    }
}


2.利用canvas的drawCircle做擦除效果
效果如下:



实现代码:
package aliusa.cn;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

public class Eraser_Use_drawCircle extends Activity {

    private int SCREEN_W;

    private int SCREEN_H;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));

    }

    class MyView extends View {
        private Bitmap mBitmap;
        private Canvas mCanvas;
        private Paint mPaint;
        int x = 0;

        int y = 0;

        int r = 0;
        
        public MyView(Context context) {
            super(context);
            setFocusable(true);
            setScreenWH();
            setBackGround();
            
            // 1.if cover is a image,you can open MENU_ITEM_COMMENT bellow
            Bitmap bm = createBitmapFromSRC();
            // if you want to set cover image's alpha,you can open MENU_ITEM_COMMENT bellow
            bm = setBitmapAlpha(bm, 100);
            // if you want to scale cover image,you can open MENU_ITEM_COMMENT bellow
            bm = scaleBitmapFillScreen(bm);

            // 2.if cover is color
            //Bitmap bm = createBitmapFromARGB(0x8800ff00, SCREEN_W, SCREEN_H);
            setCoverBitmap(bm);

        }

        private void setScreenWH() {
            // get screen info
            DisplayMetrics dm = new DisplayMetrics();
            dm = this.getResources().getDisplayMetrics();
            // get screen width
            int screenWidth = dm.widthPixels;
            // get screen height
            int screenHeight = dm.heightPixels;

            SCREEN_W = screenWidth;
            SCREEN_H = screenHeight;
        }

        private Bitmap createBitmapFromSRC() {
            return BitmapFactory.decodeResource(getResources(),
                                                R.drawable.cover);
        }

        /**
         * 
         * @param colorARGB should like 0x8800ff00
         * @param width
         * @param height
         * @return
         */
        private Bitmap createBitmapFromARGB(int colorARGB, int width, int height) {
            int[] argb = new int[width * height];

            for (int i = 0; i < argb.length; i++) {

                argb[i] = colorARGB;

            }
            return Bitmap.createBitmap(argb, width, height, Config.ARGB_8888);
        }

        /**
         * 
         * @param bm
         * @param alpha ,and alpha should be like ox00000000-oxff000000
         * @note set bitmap's alpha
         * @return
         */
       /* private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());


            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }*/
        
        /**
         * 
         * @param bm
         * @param alpha ,alpha should be between 0 and 255
         * @note set bitmap's alpha
         * @return
         */
        private Bitmap setBitmapAlpha(Bitmap bm, int alpha) {
            int[] argb = new int[bm.getWidth() * bm.getHeight()];
            bm.getPixels(argb, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm
                    .getHeight());

            for (int i = 0; i < argb.length; i++) {

                argb[i] = ((alpha << 24) | (argb[i] & 0x00FFFFFF));
            }
            return Bitmap.createBitmap(argb, bm.getWidth(), bm.getHeight(),
                                       Config.ARGB_8888);
        }
        
        /**
         * 
         * @param bm
         * @note if bitmap is smaller than screen, you can scale it fill the screen.
         * @return 
         */
        private Bitmap scaleBitmapFillScreen(Bitmap bm) {
            return Bitmap.createScaledBitmap(bm, SCREEN_W, SCREEN_H, true);
        }

        
        private void setBackGround() {
            setBackgroundResource(R.drawable.background);
        }

        /**
         * 
         * @param bm
         * @note set cover bitmap , which  overlay on background. 
         */
        private void setCoverBitmap(Bitmap bm) {
            // setting paint
            mPaint = new Paint();
            mPaint.setAlpha(0);
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mPaint.setAntiAlias(true);

            // converting bitmap into mutable bitmap
            mBitmap = Bitmap.createBitmap(SCREEN_W, SCREEN_H, Config.ARGB_8888);
            mCanvas = new Canvas();
            mCanvas.setBitmap(mBitmap);
            // drawXY will result on that Bitmap
            // be sure parameter is bm, not mBitmap
            mCanvas.drawBitmap(bm, 0, 0, null);
        }

       

        @Override
        protected void onDraw(Canvas canvas) {
         // draw a circle that is erasing bitmap
            mCanvas.drawCircle(x, y, r, mPaint);
            canvas.drawBitmap(mBitmap, 0, 0, null);
            super.onDraw(canvas);
        }
        
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            // set parameter to draw circle on touch event
            x = (int) event.getX();
            y = (int) event.getY();
            r = 20;
            // Atlast invalidate canvas
            invalidate();
            return true;
        }
    }
  • 大小: 52.7 KB
  • 大小: 56.6 KB
分享到:
评论

相关推荐

    Android 使用 PorterDuff.Mode.XOR 自定义遮罩

    遮罩视图

    Android代码-DownloadLoadingView

    &gt; 在工作中难免遇到自定义 View 的相关需求,本身这方面比较薄弱,因此做个记录,也是自己学习和成长的积累。自定义View实战 前言 ... setXfermode() 用于设置图像的过度模式,其中 PorterDuff.Mode.

    Android ShimmerLayout实现微光效果解析

    这里我们采用的是PorterDuff.MODE.SRC_IN,意思是在绘制的时候,显示上下图层相交的部分,且这部分显示上层图层。 1) 首先我们需要绘制出最上层的微光,这里通过LinearGradient线性渐变渲染器来绘制微光渐变效果,...

    Android 实现图片生成卷角和圆角缩略图的方法

    在 Android 的一些界面中,有时候我们需要为一副图片生成大小为 n * n 的缩略图,有时候需要的缩略图特殊一些,比如: ...paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XXX); canvas.drawBitmap(srcBmp

    Android自定义View实现水面上涨效果

    1、如何实现圆中水面上涨效果:利用Paint的setXfermode属性为PorterDuff.Mode.SRC_IN画出进度所在的矩形与圆的交集实现 2、如何水波纹效果:利用贝塞尔曲线,动态改变波峰值,实现“随着进度的增加,水波纹逐渐变小...

    Android UI效果之绘图篇(三)

    一、 PorterDuffXfermode PorterDuffXfermode类似于数据集合里面的交集...paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XXX)); canvas.drawDst(); 只需要更具我们的需要设置不同的Mode即可,从此以后

    Android自定义AvatarImageView实现头像显示效果

    看看效果图: 我们项目中头像显示一般都是圆形的,但是有时候不排除各种样式(不一定是个规则的形状),比如 上次UI给了我一个 圆形下面少了一块。我们一般实现自定义形状的图形有三种方式:...1.PorterDuff.Mode.CLEA

    Xfermode16-PorterDuff及Xfermode.rar

    PorterDuff及Xfermode 贝塞尔曲线

    自定义dialog

    PorterDuff.Mode localMode = PorterDuff.Mode.DST_IN; MASK_XFERMODE = new PorterDuffXfermode(localMode); } public MaskedImage(Context paramContext) { super(paramContext); } public MaskedImage...

    Android自定义Drawable之在Drawable中部指定透明区域方法示例

    前言 Drawable是什么? 一种可以在Canvas上进行绘制的抽象的概念 颜色、图片等都可以是一个Drawable Drawable可以通过XML定义,或者通过代码创建 ... 主要用到的技术是PorterDuffXfermode的PorterDuff.M

    AndroidAnimation-Android自定义View之星球运动.zip

     paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)  canvas.drawBitmap(srcB, width / -2F, height / -2F , paint)  paint.xfermode = null } //设置源图层 fun makeSrc...

    android自定义View扫描人脸效果

    本文利用SrcIn实现一个人脸扫描的效果,步骤如下: 1、准备两个人脸照片(一明一暗),暗照片作为背景,亮照片作为src前景显示 2、然后通过SrcIn用一个透明矩形框(Dst)与亮照片(src)取交集即可得出一个亮照片的...

    TanTanRippleView-仿探探进入 扫描view.zip

     val sc = canvas.saveLayer(rectF, backPaint, Canvas.ALL_SAVE_FLAG)然后再drawCircle之后在设置xfermode backPaint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.DST_OUT))这里采取DST_OUT,为什么...

    Android-PorterDuff:用于试验 PorterDuff 绘画模式的小型 Android 应用程序

    Android-PorterDuff 用于试验 PorterDuff 绘画模式的小型 Android 应用程序。

    Android.User.Interface.Design.0321886739.epub

    how to leverage advanced drawing techniques such as PorterDuff compositing; how to test designs on diverse Android devices; and much more. Android User Interface Design details each step of the ...

    简单实现Android刮刮卡效果

    本文实例为大家分享了Android仿刮刮卡效果展示的具体代码,供大家参考,具体内容如下 一、Xfermode 通过使用Xfermode将绘制的图形的像素和Canvas上对应位置的像素按照一定的规则进行混合,形成新的像素,再更新到...

    使用SurfaceView实现视频弹幕

    本文实例为大家分享了SurfaceView视频弹幕展示的具体代码,供大家参考,具体内容如下 全部代码如下: ...import android.graphics.PorterDuff; import android.media.MediaPlayer; import android.os.

    workspace.zip

    这个叫PorterDuff颜色滤镜,也叫图形混合滤镜;其名称是Tomas Proter和Tom Duff两个人名的缩写,他们提出的图形混合的概念极大地推动了图形图像学的发展。 这个颜色滤镜的声明如下: 主要显示各个模式的效果

    Android SurfaceView画板操作

    本文实例为大家分享了Android SurfaceView画板操作的具体代码,供大家参考,具体内容如下 画板——画路径 ... import android.content.Context;...import android.graphics.PorterDuff; import android

Global site tag (gtag.js) - Google Analytics