您的位置:首页 > 移动开发 > Android开发

android自定义view实现"偷窥"图片

2015-10-29 22:12 162 查看
今天实现了利用自定义view实现了一个查看被遮盖的图片功能,不过是通过”偷窥”这种行为实现的,其实这种功能我也不知道怎么命名,就暂且叫他”偷窥”图片,先看下效果吧:



ok,其实该功能和刮刮卡的原理是一样的,只不过刮刮卡对于上层的覆盖层只绘制了一次,所以每次擦除部分是不会恢复的,而对于该实例,上面的图层是每次重绘的时候都会重新绘制的,下实现该功能的原理:

实现思路

首先将准备好的图片缩放至和屏幕大小相同

在onDraw方法提供的canvas中绘制该图片

在onDraw方法提供的canvas中绘制一个和该图片相同大小的bitmap

设置当前画笔的xformode=DST_IN,以及颜色透明,这样才可以看到下面这张图片

绘制当前的圆形,注意需要设置该圆半径的初始值=0,这样不至于一开始就可以看到底层图片

重写onTouchEvent,在用户触摸该view时候,将半径更改到一定的值,并且在手指移动的时候,重新设置当前圆的圆心坐标,在手指抬起的时候,将半径重置为0,重绘,这样就实现了上面的功能。

重写onDraw方法

[code]@Override
protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //创建一个当前屏幕大小的dstBitmap并根据该dstBitmap创建相同大小的mDstCanvas
        mDstBtimap = Bitmap.createBitmap(screenWidth, screenHeight, Config.ARGB_8888);
        mDstCanvas = new Canvas(mDstBtimap);
        mDstCanvas.drawColor(Color.parseColor("#ccc568"));

        //获得mSrcBitmap,并将其缩放至和屏幕大小相同
        mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.system);
        mSrcBitmap = Bitmap.createScaledBitmap(mSrcBitmap, screenWidth, screenHeight, false);

        //先绘制底层的图片,然后绘制相同大小的mDstBtimap使其覆盖底层的图皮
        canvas.drawBitmap(mSrcBitmap, 0, 0, null);
        canvas.drawBitmap(mDstBtimap, 0, 0,null);

        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mPaint.setColor(Color.argb(20,255,0,0));//设置此时的画笔为透明,所以可以看到底层的图片
        mDstCanvas.drawCircle(mCurrentX, mCurrentY, mShowCircleRadius, mPaint);
    }


这里和我上面描述的原理是一样的,先绘制一个图片,然后绘制一个相同大小的bitmap,遮挡住该图片,设置Paint的模式和透明色,绘制圆。

重写onTouchEvent

[code]@Override
public boolean onTouchEvent(MotionEvent event) {

        //每次onTouchEvent方法调用的时候需要重新将手指按下的坐标赋值给圆心坐标,否做会出现当手指抬起后再次按下时候,会在上一个手指抬起时候的坐标显示
        //因为mCurrentX 和mCurrentY最后的值就是手指抬起时候的按下的值
        mCurrentX = event.getX();
        mCurrentY = event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            //当手指按下的时候,将当前圆的半径变为一定的值
            mShowCircleRadius += mRadius; 

            break;
        case MotionEvent.ACTION_MOVE:
            //获取当前手指按下的坐标,将将其标注为圆心
            mCurrentX = event.getX();
            mCurrentY = event.getY();

            //边界条件判断
            mCurrentX = mCurrentX < mRadius ? mRadius : mCurrentX;
            mCurrentY = mCurrentY < mRadius ? mRadius : mCurrentY;

            mCurrentX = (mCurrentX + mRadius) > screenWidth ? (screenWidth - mRadius) : mCurrentX; 
            mCurrentY = (mCurrentY + mRadius + getStatusBarHeight()) > screenHeight ? (screenHeight - mRadius - getStatusBarHeight()) : mCurrentY; 

            Log.d(TAG, "the mCurrentY is :"+mCurrentY+"====the screenHeight is :"+screenHeight+":status bar:"+getStatusBarHeight());
            break;
        case MotionEvent.ACTION_UP:
            mShowCircleRadius = 0;
            break;
        default:
            break;
        }

        invalidate();
        return true;

    }


代码注释的比较详细,就不做过多解释了,注意一点,在做边界条件判断的时候,由于最下面的地方需要将手机状态栏的高度考虑进去,因为我们是和整个屏幕的高度来做比较的。

获取状态栏的高度

[code]private int getStatusBarHeight(){
        int height=0;
        int resouceId=getResources().getIdentifier("status_bar_height", "dimen", "android");
        if(resouceId>0){
            height=getResources().getDimensionPixelSize(resouceId);
        }
        return height;
    }


可以看到这里我使用资源id首先查找到资源id,然后通过getResources来查看具体的值。

ok,今天的博客就到这里了,希望大家能够喜欢。

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: