图片滑动验证Demo

来源:互联网 发布:绝世唐门进阶数据 编辑:程序博客网 时间:2024/06/05 17:20

首先说一下思路,首先绘制一个闭合路径来作为可移动的图片块的形状,在对应的背景图片位置绘制该路径并填充为灰色,接着在新建一个同样大小的图片,背景设为透明,以及一个对应新的Canvas,利用该路径切割Canvas,并绘制背景图片,此时该图片只有路径区域显示背景图片对应位置其他区域为透明,接着重写onDraw(),接着绘制这两张图片,并通过监听move事件移动背景透明的图片。效果如图:
这里写图片描述

下面是源码:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
* Created by lc on 16-12-26.
*/

public class MySlideImage extends View {
private int backgroundId;//验证图片资源ID
private int drawX;//随机生成的x坐标
private int drawY;//随机生成的Y坐标
private boolean backgroundHasDraw = false;//是否时第一次绘制
private int width;//资源图片宽度
private int height;//资源图片高度
private int targetWidth;//图片块宽度
private int targetHeight;//图片块高度
private MoveFinishBack mMoveFinishBack = null;//验证完成后回调接口
private Path mPath;//图片块路径
Bitmap mBitmap;//验证图片
private float lastX = 0;//监听滑动事件上一次坐标
private int targetLength;//可移动图片块所在图片距离左边缘距离,范围为(-drawX,0)
private int moveLength = 12;//底部圆心距离左边缘距离

public MySlideImage(Context context) {    super(context);}public MySlideImage(Context context, AttributeSet attrs) {    super(context, attrs);    TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MySlideImage);    backgroundId = array.getResourceId(R.styleable.MySlideImage_imageSrc, 0);    mBitmap = getBitmapById(backgroundId);    width = mBitmap.getWidth();    height = mBitmap.getHeight();    Log.d("lc", "backgroundId = " + backgroundId + "height  = " + height + " width = " + width);    array.recycle();}/*    创建可移动图块,只有路径所围成的区域可见,其他为透明 */public Bitmap createMoveDrawable() {    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//创建可移动图片    Canvas canvas = new Canvas(bitmap);    canvas.clipPath(getPath());//截取画布,目的只显示需要的图片区域    Paint paint = new Paint();    paint.setAntiAlias(true);    if (mBitmap != null) {        // canvas.drawBitmap(mBitmap, new Rect(drawX,drawY,drawX+targetWidth,drawY+targetHeight), new RectF(drawX,drawY,drawX+targetWidth,drawY+targetHeight), paint);        canvas.drawBitmap(mBitmap, 0, 0, paint);    } else {        Log.d("lc", "createTargetDrawable :bitmap is null");    }    return bitmap;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    setMeasuredDimension(width, height + 30);}/*    创建底部背景 */public void createTargetDrawable(Canvas canvas) {    Paint paint = new Paint();    paint.setColor(Color.GRAY);    paint.setAntiAlias(true);    paint.setStyle(Paint.Style.FILL_AND_STROKE);    if (mBitmap != null) {        canvas.drawBitmap(mBitmap, 0, 0, paint);    } else {        Log.d("lc", "createTargetDrawable :bitmap is null");    }    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));    paint.setColor(Color.GREEN);    canvas.drawPath(getPath(), paint);    backgroundHasDraw = true;}public void getRandomXY() {    double random = Math.random();    random = random > (5 * 1.00 / 6) ? (5 * 1.00 / 6) : (random > 1.00 / 6 ? random : 1.00 / 6);    Log.d("lc", " random = " + random);    drawX = (int) (width * random);    drawY = (int) (height * random);    Log.d("lc", " drawX = " + drawX + " drawY = " + drawY);    targetHeight = height / 6;    targetWidth = width / 6;    Log.d("lc", " targetHeight = " + targetHeight + " targetWidth = " + targetWidth);}@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    Paint paint = new Paint();    paint.setAntiAlias(true);    if (!backgroundHasDraw) {        getRandomXY();        targetLength = -drawX;        moveLength = 12;    }    drawSeekBar(canvas, paint);    createTargetDrawable(canvas);    canvas.drawBitmap(createMoveDrawable(), targetLength, 0, paint);    drawSeekButton(canvas, paint);}public Bitmap getBitmapById(int resourceId) {    return BitmapFactory.decodeResource(getContext().getResources(), resourceId);}public Path getPath() {    if (mPath == null) {        mPath = new Path();        mPath.moveTo(drawX, drawY);        mPath.lineTo(drawX + 10, drawY);        mPath.lineTo(drawX + 10, drawY + 15);        mPath.lineTo(drawX + targetWidth, drawY + 15);        mPath.lineTo(drawX + targetWidth, drawY + targetHeight);        mPath.lineTo(drawX, drawY + targetHeight);        mPath.lineTo(drawX, drawY);    }    return mPath;}/*    绘制底部绿色bar */public void drawSeekBar(Canvas canvas, Paint paint) {    paint.setColor(Color.GREEN);    paint.setStyle(Paint.Style.FILL_AND_STROKE);    canvas.drawRoundRect(new RectF(5, height + 10, width - 5, height + 20), 0.5f, 0.5f, paint);}/*    绘制底部红色圆 */public void drawSeekButton(Canvas canvas, Paint paint) {    paint.setColor(Color.RED);    paint.setStyle(Paint.Style.FILL_AND_STROKE);    canvas.drawCircle(moveLength, height + 12, 12, paint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {    int action = event.getAction();    switch (action) {        case MotionEvent.ACTION_DOWN:            lastX = event.getX();            Log.d("lc", "action down");            break;        case MotionEvent.ACTION_MOVE:            float currentX = event.getX();            int length = (int) (currentX - lastX);            Log.d("lc", "action move  length = " + length);            moveLength = Math.max(12, Math.min(width - 12, moveLength + length));            targetLength = Math.max(-drawX, Math.min(width - targetWidth, targetLength + length));            invalidate();            lastX = currentX;            break;        case MotionEvent.ACTION_UP:            boolean finished = false;            if (Math.abs(targetLength) < 6) {                finished = true;                Log.d("lc", " action up " + finished);                targetLength = 0;                postInvalidateDelayed(300);            } else {                Log.d("lc", " action up " + finished);                moveLength = 12;                targetLength = -drawX;                postInvalidateDelayed(300);            }            if (mMoveFinishBack != null) {                if (finished) {                    mMoveFinishBack.MoveFinish(true);                } else {                    mMoveFinishBack.MoveFinish(false);                }            }            break;    }    return true;}public void setCallBack(MoveFinishBack moveFinishBack) {    this.mMoveFinishBack = moveFinishBack;}/*    自定义路径以及设置图片块宽高 */public void setPathAndRect(Path path,int height,int width) {    mPath = path;    targetWidth = width;    targetHeight = height;}/*    刷新图片 */public void refreshImage(){    backgroundHasDraw = false;    mPath = null;    invalidate();}interface MoveFinishBack {    void MoveFinish(boolean correct);}}说明:    1.上面代码中未对图片大小进行判断,所以测试大的图片时需要先对其进行尺寸压缩。    2.图片块的位置采用随机值    3.上例中图片的资源Id是通过自定义属性获得    4.部分手机(图片块只显示为一个矩形)需要在清单文件中关闭硬件加速才能看到完整效果
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 换了手机支付宝怎么办 手机丢了微信登不上去了怎么办 前面手机丢了微信登不上去怎么办 淘宝密码忘了怎么办呢 融e借逾期一天怎么办 拼多多处罚下架怎么办 永久无法解绑支付宝怎么办 淘宝下单购买人数太多怎么办 新浪微博被拉黑暂时无法评论怎么办 闲鱼交易成功后卖家反悔怎么办 闲鱼买家不申请介入怎么办 支付宝安装不上怎么办 无线摄像机离wifi太远怎么办 安卓系统死机了怎么办 安卓手机开不了机怎么办 手机关机键坏了怎么办 华为手机接听电话声音小怎么办 小米6x游戏闪退怎么办 安卓8.0不兼容怎么办 安卓8.0应用闪退怎么办 安卓8.0不兼容的怎么办 游戏全屏只有一个分辨率选项怎么办 安卓6.0吃运行内存怎么办 小米手机王者荣耀录像不支持怎么办 win764位系统不兼容怎么办 安卓版本太高不兼容怎么办 安卓3.2.0不兼容怎么办 手机卡和手机不兼容怎么办 vivo手机下载吃鸡不兼容怎么办 vivox3t不兼容支付宝怎么办 移动sim卡坏了怎么办 cpu和主板不兼容怎么办 主板与cpu不兼容怎么办 cpu跟主板不兼容怎么办 软件与电脑不兼容怎么办 win8系统无限重启怎么办 安装微信旧版本登录提示升级怎么办 手机软件与系统不兼容怎么办 下载旧版本微信闪退登陆不了怎么办 企业微信一直登录失败怎么办 360浏览器9.1经常卡死怎么办