可移动缩放拖拽的ViewfinderView

来源:互联网 发布:mac unix 可执行文件 编辑:程序博客网 时间:2024/05/17 23:55

这里写图片描述为了这个可以拖拽的扫描框,着实头痛了几天
主要借鉴文章:http://blog.csdn.net/farble/article/details/44235555
public final class ViewfinderView extends View {
private static final String TAG = “log”;
/**
* 刷新界面的时间
*/
private static final long ANIMATION_DELAY = 10L;
private static final int OPAQUE = 0xFF;

/** * 四个绿色边角对应的长度 */private int ScreenRate;/** * 四个绿色边角对应的宽度 */private static final int CORNER_WIDTH = 10;/** * 扫描框中的中间线的宽度 */private static final int MIDDLE_LINE_WIDTH = 6;/** * 扫描框中的中间线的与扫描框左右的间隙 */private static final int MIDDLE_LINE_PADDING = 5;/** * 中间那条线每次刷新移动的距离 */private static final int SPEEN_DISTANCE = 5;/** * 手机的屏幕密度 */private static float density;/** * 字体大小 */private static final int TEXT_SIZE = 16;/** * 字体距离扫描框下面的距离 */private static final int TEXT_PADDING_TOP = 30;/** * 画笔对象的引用 */private Paint paint;/** * 中间滑动线的最顶端位置 */private int slideTop;/** * 中间滑动线的最底端位置 */private int slideBottom;/** * 将扫描的二维码拍下来,这里没有这个功能,暂时不考虑 */private Bitmap resultBitmap;private final int maskColor;private final int resultColor;private final int resultPointColor;private Collection<ResultPoint> possibleResultPoints;private Collection<ResultPoint> lastPossibleResultPoints;boolean isFirst;//TODO startprivate onLocationListener locationListener;/*listen to the Rect */private onChangeLocationlistener changeLocationlistener;/*listening position changed */private int MODE;private static final int MODE_OUTSIDE = 0x000000aa;/*170*/private static final int MODE_INSIDE = 0x000000bb;/*187*/private static final int MODE_POINT = 0X000000cc;/*204*/private static final int MODE_ILLEGAL = 0X000000dd;/*221*/private static final int minWidth = 100;/*the minimum width of the rectangle*/private static final int minHeight = 200;/*the minimum height of the rectangle*/private static final int START_X = 200;private static final int START_Y = 200;private static final float EDGE_WIDTH = 1.8f;private static final int ACCURACY = 15;/*touch accuracy*/private int pointPosition;/*vertex of a rectangle*/private int sX;/*start X location*/private int sY;/*start Y location*/private int eX;/*end X location*/private int eY;/*end Y location*/private int pressX;/*X coordinate values while finger press*/private int pressY;/*Y coordinate values while finger press*/private int memonyX;/*the last time the coordinate values of X*/private int memonyY;/*the last time the coordinate values of Y*/private int coverWidth = 600;/*width of selection box*/private int coverHeight = 720;/*height of selection box*/private Paint mPaint;private Paint mPaintLine;private Bitmap mBitmapCover;private Bitmap mBitmapRectBlack;private PorterDuffXfermode xfermode;/*paint mode*///TODO endpublic ViewfinderView(Context context, AttributeSet attrs) {    super(context, attrs);    init();    density = context.getResources().getDisplayMetrics().density;    //将像素转换成dp    ScreenRate = (int) (20 * density);    paint = new Paint();    Resources resources = getResources();    maskColor = resources.getColor(R.color.viewfinder_mask);    resultColor = resources.getColor(R.color.result_view);    resultPointColor = resources.getColor(R.color.possible_result_points);    possibleResultPoints = new HashSet<ResultPoint>(5);}@SuppressWarnings("deprecation")private void init() {   /* sX = START_X;    sY = START_Y;*/    WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);    int width = manager.getDefaultDisplay().getWidth();    int height = manager.getDefaultDisplay().getHeight();    mBitmapCover = makeBitmap(width, height, 0x5A000000, 0, 0);    mBitmapRectBlack = makeBitmap(coverWidth, coverHeight, 0xff000000, coverWidth, coverHeight);    sX = width / 2 - coverWidth / 2;    sY = height / 2 - coverHeight / 2;    eX = sX + coverWidth;    eY = sY + coverHeight;    pressX = 0;    pressY = 0;    xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);    mPaint = new Paint();    mPaint.setAntiAlias(true);    mPaintLine = new Paint();    mPaintLine.setColor(Color.WHITE);    mPaintLine.setStrokeWidth(2.0f);}/*生成bitmap*/private Bitmap makeBitmap(int mwidth, int mheight, int resource, int staX, int staY) {    Bitmap bm = Bitmap.createBitmap(mwidth, mheight, Bitmap.Config.ARGB_8888);    Canvas c = new Canvas(bm);    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);    p.setColor(resource);    c.drawRect(staX, staY, mwidth, mheight, p);    return bm;}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {    //请求父控件不拦截触摸事件    getParent().requestDisallowInterceptTouchEvent(true);    return super.dispatchTouchEvent(event);}@SuppressWarnings("NullableProblems")@Overridepublic boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            if (changeLocationlistener != null) {                changeLocationlistener.locationChange("change self");            } else {                changeLocationlistener = null;            }            memonyX = (int) event.getX();            memonyY = (int) event.getY();            checkMode(memonyX, memonyY);            break;        case MotionEvent.ACTION_MOVE: {            switch (MODE) {                case MODE_ILLEGAL:                    pressX = (int) event.getX();                    pressY = (int) event.getY();                    recoverFromIllegal(pressX, pressY);                    postInvalidate();                    break;                case MODE_OUTSIDE:                    //do nothing;                    break;                case MODE_INSIDE:                    pressX = (int) event.getX();                    pressY = (int) event.getY();                    moveByTouch(pressX, pressY);                    postInvalidate();                    break;                default:                        /*MODE_POINT*/                    pressX = (int) event.getX();                    pressY = (int) event.getY();                    mPaintLine.setColor(getContext().getResources().getColor(R.color.white));                    moveByPoint(pressX, pressY);                    postInvalidate();                    break;            }        }        break;        case MotionEvent.ACTION_UP:            mPaintLine.setColor(Color.WHITE);            postInvalidate();            break;        default:            break;    }    return true;}/*从非法状态恢复,这里处理的是达到最小值后能拉伸放大*/private void recoverFromIllegal(int rx, int ry) {    if ((rx > sX && ry > sY) && (rx < eX && ry < eY)) {        MODE = MODE_ILLEGAL;    } else {        MODE = MODE_POINT;    }}private void checkMode(int cx, int cy) {    if (cx > sX && cx < eX && cy > sY && cy < eY) {        MODE = MODE_INSIDE;    } else if (nearbyPoint(cx, cy) < 4) {        MODE = MODE_POINT;    } else {        MODE = MODE_OUTSIDE;    }}/*判断点(inX,inY)是否靠近矩形的4个顶点*/private int nearbyPoint(int inX, int inY) {    if ((Math.abs(sX - inX) <= ACCURACY && (Math.abs(inY - sY) <= ACCURACY))) {/*left-up angle*/        pointPosition = 0;        return 0;    }    if ((Math.abs(eX - inX) <= ACCURACY && (Math.abs(inY - sY) <= ACCURACY))) {/*right-up  angle*/        pointPosition = 1;        return 1;    }    if ((Math.abs(sX - inX) <= ACCURACY && (Math.abs(inY - eY) <= ACCURACY))) {/*left-down angle*/        pointPosition = 2;        return 2;    }    if ((Math.abs(eX - inX) <= ACCURACY && (Math.abs(inY - eY) <= ACCURACY))) {/*right-down angle*/        pointPosition = 3;        return 3;    }    pointPosition = 100;    return 100;}/*刷新矩形的坐标*/private void refreshLocation(int isx, int isy, int iex, int iey) {    this.sX = isx;    this.sY = isy;    this.eX = iex;    this.eY = iey;}/*矩形随手指移动*/private void moveByTouch(int mx, int my) {/*move center point*/    int dX = mx - memonyX;    int dY = my - memonyY;    sX += dX;    sY += dY;    eX = sX + coverWidth;    eY = sY + coverHeight;    memonyX = mx;    memonyY = my;}/*检测矩形是否达到最小值*/private boolean checkLegalRect(int cHeight, int cWidth) {    return (cHeight > minHeight && cWidth > minWidth);}/*点击顶点附近时的缩放处理*/@SuppressWarnings("SuspiciousNameCombination")private void moveByPoint(int bx, int by) {    switch (pointPosition) {        case 0:/*left-up*/            coverWidth = Math.abs(eX - bx);            coverHeight = Math.abs(eY - by);            //noinspection SuspiciousNameCombination            if (!checkLegalRect(coverWidth, coverHeight)) {                MODE = MODE_ILLEGAL;            } else {                mBitmapRectBlack = null;                mBitmapRectBlack = makeBitmap(coverWidth, coverHeight, 0xff000000, coverWidth, coverHeight);                refreshLocation(bx, by, eX, eY);            }            break;        case 1:/*right-up*/            coverWidth = Math.abs(bx - sX);            coverHeight = Math.abs(eY - by);            if (!checkLegalRect(coverWidth, coverHeight)) {                MODE = MODE_ILLEGAL;            } else {                mBitmapRectBlack = null;                mBitmapRectBlack = makeBitmap(coverWidth, coverHeight, 0xff000000, coverWidth, coverHeight);                refreshLocation(sX, by, bx, eY);            }            break;        case 2:/*left-down*/            coverWidth = Math.abs(eX - bx);            coverHeight = Math.abs(by - sY);            if (!checkLegalRect(coverWidth, coverHeight)) {                MODE = MODE_ILLEGAL;            } else {                mBitmapRectBlack = null;                mBitmapRectBlack = makeBitmap(coverWidth, coverHeight, 0xff000000, coverWidth, coverHeight);                refreshLocation(bx, sY, eX, by);            }            break;        case 3:/*right-down*/            coverWidth = Math.abs(bx - sX);            coverHeight = Math.abs(by - sY);            if (!checkLegalRect(coverWidth, coverHeight)) {                MODE = MODE_ILLEGAL;            } else {                mBitmapRectBlack = null;                mBitmapRectBlack = makeBitmap(coverWidth, coverHeight, 0xff000000, coverWidth, coverHeight);                refreshLocation(sX, sY, bx, by);            }            break;        default:            break;    }}public void setLocationListener(onLocationListener locationListener) {    this.locationListener = locationListener;}public interface onLocationListener {    public void locationRect(int startX, int startY, int endX, int endY);}public interface onChangeLocationlistener {    @SuppressWarnings("SameParameterValue")    public void locationChange(String msg);}@Overridepublic void onDraw(Canvas canvas) {    super.onDraw(canvas);    //获取屏幕的宽和高    int screenWidth = canvas.getWidth();    int screenHeight = canvas.getHeight();    mPaint.setFilterBitmap(false);    int sc = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.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(mBitmapCover, 0, 0, mPaint);    mPaint.setXfermode(xfermode);    canvas.drawBitmap(mBitmapRectBlack, sX, sY, mPaint);    if (locationListener != null) {        locationListener.locationRect(sX, sY, eX, eY);    }    mPaint.setXfermode(null);    canvas.restoreToCount(sc);    //canvas.drawLine((float) sX - EDGE_WIDTH, (float) sY - EDGE_WIDTH, (float) eX + EDGE_WIDTH, (float) sY - EDGE_WIDTH, mPaintLine);/*up -*/    //canvas.drawLine((float) sX - EDGE_WIDTH, (float) eY + EDGE_WIDTH, (float) eX + EDGE_WIDTH, (float) eY + EDGE_WIDTH, mPaintLine);/*down -*/    //canvas.drawLine((float) sX - EDGE_WIDTH, (float) sY - EDGE_WIDTH, (float) sX - EDGE_WIDTH, (float) eY + EDGE_WIDTH, mPaintLine);/*left |*/    //canvas.drawLine((float) eX + EDGE_WIDTH, (float) sY - EDGE_WIDTH, (float) eX + EDGE_WIDTH, (float) eY + EDGE_WIDTH, mPaintLine);/*righ |*/    //TODO  画出八个角    float left = sX - EDGE_WIDTH;    float top = sY - EDGE_WIDTH;    float right = eX + EDGE_WIDTH;    float bottom = eY + EDGE_WIDTH;   /* //如果矩形框 已经超出屏幕 不再继续移动    if (sX <= 0 || eX >= screenWidth || sY <= 0 || eY >= screenHeight) {        return ;    }*/    if (!isFirst) {        isFirst = true;        slideTop = (int) top;        slideBottom = (int) bottom;    }    Paint paint = new Paint();    paint.setColor(Color.GREEN);    //1 左上    canvas.drawRect(left, top, left + ScreenRate,            top + CORNER_WIDTH, paint);    canvas.drawRect(left, top, left + CORNER_WIDTH, top            + ScreenRate, paint);    //2 右上    canvas.drawRect(right - ScreenRate, top, right,            top + CORNER_WIDTH, paint);    canvas.drawRect(right - CORNER_WIDTH, top, right, top            + ScreenRate, paint);    //3 左下    canvas.drawRect(left, bottom - CORNER_WIDTH, left            + ScreenRate, bottom, paint);    canvas.drawRect(left, bottom - ScreenRate,            left + CORNER_WIDTH, bottom, paint);    //4 右下    canvas.drawRect(right - ScreenRate, bottom - CORNER_WIDTH,            right, bottom, paint);    canvas.drawRect(right - CORNER_WIDTH, bottom - ScreenRate,            right, bottom, paint);    //绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE    slideTop += SPEEN_DISTANCE;    if (slideTop >= bottom) {        slideTop = (int) top;    }    canvas.drawRect(left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH / 2, right - MIDDLE_LINE_PADDING, slideTop + MIDDLE_LINE_WIDTH / 2, paint);    //画扫描框下面的字    paint.setColor(Color.WHITE);    paint.setTextSize(TEXT_SIZE * density);    paint.setAlpha(0x40);    paint.setTypeface(Typeface.create("System", Typeface.BOLD));    canvas.drawText(getResources().getString(R.string.scan_text), left + 30, (float) (bottom + (float) TEXT_PADDING_TOP * density), paint);    paint.setColor(getResources().getColor(R.color.b_commit));    canvas.drawText(getResources().getString(R.string.scan_notice), left, (float) (bottom + (float) TEXT_PADDING_TOP * density + 50), paint);    Collection<ResultPoint> currentPossible = possibleResultPoints;    Collection<ResultPoint> currentLast = lastPossibleResultPoints;    if (currentPossible.isEmpty()) {        lastPossibleResultPoints = null;    } else {        possibleResultPoints = new HashSet<ResultPoint>(5);        lastPossibleResultPoints = currentPossible;        paint.setAlpha(OPAQUE);        paint.setColor(resultPointColor);        for (ResultPoint point : currentPossible) {            canvas.drawCircle(left + point.getX(), top                    + point.getY(), 6.0f, paint);        }    }    if (currentLast != null) {        paint.setAlpha(OPAQUE / 2);        paint.setColor(resultPointColor);        for (ResultPoint point : currentLast) {            canvas.drawCircle(left + point.getX(), top                    + point.getY(), 3.0f, paint);        }    }    //只刷新扫描框的内容,其他地方不刷新    postInvalidateDelayed(ANIMATION_DELAY, (int) left, (int) top,            (int) right, (int) bottom);}public void drawViewfinder() {    resultBitmap = null;    invalidate();}/** * Draw a bitmap with the result points highlighted instead of the live * scanning display. * * @param barcode An image of the decoded barcode. */public void drawResultBitmap(Bitmap barcode) {    resultBitmap = barcode;    invalidate();}public void addPossibleResultPoint(ResultPoint point) {    possibleResultPoints.add(point);}

}

0 0