可移动缩放拖拽的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
- 可移动缩放拖拽的ViewfinderView
- 二维码-ViewFinderView的使用
- 自定义的可缩放可移动的layout
- view 的拖拽移动,旋转缩放
- Android:手把手教你打造可缩放移动的ImageView
- [Android View] 判断是否点中一个动态可旋转、可缩放、可移动的图片
- 可缩放的ImageView
- 图片拖拽、旋转、缩放、移动
- Android:手把手教你打造可缩放移动的ImageView(上)
- Android:手把手教你打造可缩放移动的ImageView(下)
- Android:手把手教你打造可缩放移动的ImageView(上)
- 可缩放的显示区
- IOS 实现可移动拖拽的View
- 图片的移动和缩放
- 视图的移动,旋转,缩放
- 图片的缩放和移动
- 摄像机的旋转,移动,缩放
- Android图片查看器(图片可移动、缩放、旋转)
- C++实验2—分段函数求值
- 一图读懂JVM架构解析
- IAR平台上位变量的简单使用
- NetBeans 使用的一些小技巧
- Windows环境下jenkins +svn+android studio自动化构建(持续集成,打包)
- 可移动缩放拖拽的ViewfinderView
- 交换机三种端口模式Access、Hybrid和Trunk的理解
- NO.8 LDAP网络用户账户
- Qt 或者VS配置问题:无法解析的外部符号,无法打开包括文件,,都可归结为 没有配置好
- VC++unicode项目使用CFile类写txt日志文件
- 改变button可点击的工具类
- java enum(枚举)使用详解 + 总结
- 面向对象之路
- 引用Android 源码编译出的jar包文件