Android 仿美女撕衣服效果


因为我写demo的时候不是用一整屏幕来放置当前图片View的,且资源图也不小,所以用到了bitmap缩放

主要思想是:改变touch点的Bitmap色值为透明,并生成新的Bitmap进行显示

package com.stone.guaguaka.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.stone.guaguaka.R;

/**
 * 撕衣服
 * 跟刮刮卡类似:同样是消除上一层,保留下一层
 * 通过bitmap.setpixel(x, y, 0) 使上一层的像素点透明,而看到下一层
 * author : stone
 * email  : aa86799@163.com
 * time   : 16/1/27 22 37
 */
public class RipClothes extends RelativeLayout {

    private ImageView mIvTop;
    private ImageView mIvBottom;
    private int[] mImgAry = {R.drawable.nn1, R.drawable.nn2};
    private Bitmap mTopBitmap;
    private Bitmap mBottomBitmap;
    private int mMove = 20;


    public RipClothes(Context context) {
        this(context, null);
    }

    public RipClothes(Context context, AttributeSet attrs) {
        super(context, attrs);

        mIvTop = new ImageView(getContext());
        mIvBottom = new ImageView(getContext());

        addView(mIvBottom, new LayoutParams(-1, -1));
        addView(mIvTop, new LayoutParams(-1, -1));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureChildren(widthMeasureSpec, heightMeasureSpec);


    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed) {
            int w = mIvBottom.getWidth();
            int h = mIvBottom.getHeight();

            /* 底图使用ScaleType.MATRIX 缩放 */
            mIvBottom.setScaleType(ImageView.ScaleType.MATRIX);
            mBottomBitmap = BitmapFactory.decodeStream(getResources().openRawResource(mImgAry[0]));
            Matrix m = new Matrix();
            m.postScale(w * 1.00f / mBottomBitmap.getWidth(), h * 1.00f / mBottomBitmap.getHeight());
            mIvBottom.setImageMatrix(m);
            mIvBottom.setImageBitmap(mBottomBitmap);
            //这里的0~w 是要截取的宽度 不能大于原图位置
//          mBottomBitmap = Bitmap.createBitmap(mBottomBitmap, 0, 0, w, h, matrix, true);

            /* 上层bitmap需要是mutable的 */
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.RGB_565;
            options.inJustDecodeBounds = true; //只读宽高边界
            mTopBitmap = BitmapFactory.decodeStream(getResources().openRawResource(mImgAry[1]), null, options);
            int imgw = options.outWidth; //=w  因为 layoutParams=-1
            int imgh = options.outHeight; //=h
            options.inJustDecodeBounds = false;
            options.inSampleSize = calculateInSampleSize(options, imgw, imgh);

            //缩放后的
            mTopBitmap = BitmapFactory.decodeStream(getResources().openRawResource(mImgAry[1]), null, options);


//            Bitmap bitmap = Bitmap.createBitmap(mTopBitmap, 0, 0, w, h);  //这返回不可变的 不行
            Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);//创建空的可变位图
            Canvas canvas = new Canvas(bitmap);
            Matrix matrix = new Matrix();
            float xRatio = w * 1.00f / mTopBitmap.getWidth();//若w>bitmapW,则放大;反之缩小
            float yRatio = h * 1.00f / mTopBitmap.getHeight();
            matrix.postScale(xRatio, yRatio);//缩放成与bitmap的宽高一致
            canvas.drawBitmap(mTopBitmap, matrix, null);
            mTopBitmap = bitmap;

            mIvTop.setImageBitmap(mTopBitmap);
            mIvTop.setBackgroundColor(Color.TRANSPARENT);
        }
    }

    /**
     * 计算 图片缩小比例
     *
     * @param options
     * @param reqWidth  目标宽度
     * @param reqHeight 目标高度
     * @return
     */
    public static int calculateInSampleSize(BitmapFactory.Options options,
                                            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        //先根据宽度进行缩小
        while (width / inSampleSize > reqWidth) {
            inSampleSize++;
        }
        //然后根据高度进行缩小
        while (height / inSampleSize > reqHeight) {
            inSampleSize++;
        }
        return inSampleSize;
    }

/*    private int RADIUS = 50;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return true;
            case MotionEvent.ACTION_MOVE:
                int touchX = (int) event.getX();
                int touchY = (int) event.getY();
                // 这个判断是计算边界,因为超过了边界为负值时会报错
                if (touchX >= RADIUS
                        & touchX <= mTopBitmap.getWidth() - RADIUS
                        & touchY >= RADIUS
                        & touchY <= mTopBitmap.getHeight() - RADIUS) {
                    for (int radius = 0; radius <= RADIUS; radius++) {//RADIUS半径内的像素点设为透明
                        for (double angle = 0; angle <= 360; angle++) {
                            double newX = touchX + radius * Math.cos(angle);
                            double newY = touchY + radius * Math.sin(angle);
                            mTopBitmap.setPixel((int) newX, (int) newY, Color.TRANSPARENT);
                        }
                    }
                }
                mIvTop.setImageBitmap(mTopBitmap);
                return  true;
        }
        return super.onTouchEvent(event);
    }*/

    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                return true;
            case MotionEvent.ACTION_MOVE:
                int x = (int) event.getX();
                int y = (int) event.getY();

                /*
                    以矩形方式改变位图
                    touch点为矩形中心,
                 */
                int left = x - mMove;
                int top = y - mMove;
                int right = x + mMove;
                int bottom = y + mMove;

                for (int i = left; i < right; i++) {
                    for (int j = top; j < bottom; j++) {
                        if (i >= 0 && j >= 0 && i <= mTopBitmap.getWidth() - mMove
                                && j <= mTopBitmap.getHeight() - mMove) {
                            mTopBitmap.setPixel(i, j, Color.TRANSPARENT);
                        }

                    }
                }
                mIvTop.setImageBitmap(mTopBitmap);
                return true;
        }
        return super.onTouchEvent(event);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }
}

美女资源图地址

我的自定义View项目地址: https://github.com/aa86799/MyCustomView (欢迎start&fork)

本文地址:https://github.com/aa86799/MyCustomView/tree/master/guaguaka

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值