Android二维码(仿微信,轻量Zxing)
来源:互联网 发布:网络谩骂案例 编辑:程序博客网 时间:2024/05/21 09:53
前言
要做一个功能,二维码识别。网上找一堆相关的Demo,但是总不是想要的效果,或者都是多年前的版本,权衡考虑之后,决定亲自操刀。不纠结直接选中Zxing框架,https://github.com/zxing/zxing 在网站上直接clone下来,运行,然后就发现问题了…
选Zxing存在的问题
- 为什么是横屏,调成竖屏,居然有问题
- 这个包居然有好多用不着的代码
- 默认识别的界面不是想要的效果
- 加个Title在顶部之后识别框居然不居中
发现问题,那么本文的优点就来了,且听一一道来
- 集成速度快,相关核心功能都已经再次封装好
- 最新的V3.30的工程,识别速度快,基本见图秒识别
- 解决横竖屏的问题,通过设置Activity的android:screenOrientation=”portrait” 方式设置,就可以自适应横屏竖屏
- 去掉工程中无用的代码,留下最核心的代码,实现最最最轻量级
- 自定义AutoScannerView控件,实现微信识别区域的效果
- 解决工程之间只以屏幕为居中的问题,目前可以根据设置宽度高度自适应居中
- 具体示例参考:https://github.com/yangxixi88/ZxingLite
光说不练假把式,上动图
模仿微信的效果,真机上效果更好,录屏的将就着看
默认效果
集成方式
1、导入zxinglite工程,Andorid Studio通过Import Module方式导入
2、导入目标工程之后,如果有存在R等资源文件未找到,可以在菜单栏Build->Make Module zxinglite 即可
3、添加两个权限
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.VIBRATE" />
4、集成BaseCaptureActivity,实现getSurfaceView()和dealDecode()等方法
5、布局样式,仿微信效果则用AutoScannerView,默认效果使用com.google.zxing.client.android.ViewfinderView
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_wechat_capture" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="yangxixi.zxinglib.WeChatCaptureActivity"> <SurfaceView android:id="@+id/preview_view" android:layout_width="fill_parent" android:layout_height="fill_parent" /> <com.google.zxing.client.android.AutoScannerView android:id="@+id/autoscanner_view" android:layout_width="match_parent" android:layout_height="match_parent" /></RelativeLayout>
6、仿微信效果的Activity
/** * 模仿微信的扫描界面 */public class WeChatCaptureActivity extends BaseCaptureActivity { private static final String TAG = WeChatCaptureActivity.class.getSimpleName(); private SurfaceView surfaceView; private AutoScannerView autoScannerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wechat_capture); surfaceView = (SurfaceView) findViewById(R.id.preview_view); autoScannerView = (AutoScannerView) findViewById(R.id.autoscanner_view); } @Override protected void onResume() { super.onResume(); autoScannerView.setCameraManager(cameraManager); } @Override public SurfaceView getSurfaceView() { return (surfaceView == null) ? (SurfaceView) findViewById(R.id.preview_view) : surfaceView; } @Override public void dealDecode(Result rawResult, Bitmap barcode, float scaleFactor) { Log.i(TAG, "dealDecode ~~~~~ " + rawResult.getText() + " " + barcode + " " + scaleFactor); playBeepSoundAndVibrate(true, false); Toast.makeText(this, rawResult.getText(), Toast.LENGTH_LONG).show();// 对此次扫描结果不满意可以调用// reScan(); }}
默认效果Activity
/** * 默认的扫描界面 */public class DefaultCaptureActivity extends BaseCaptureActivity { private static final String TAG = DefaultCaptureActivity.class.getSimpleName(); private SurfaceView surfaceView; private ViewfinderView viewfinderView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_capture); surfaceView = (SurfaceView) findViewById(R.id.preview_view); viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); } @Override public SurfaceView getSurfaceView() { return (surfaceView == null) ? (SurfaceView) findViewById(R.id.preview_view) : surfaceView; } @Override public ViewfinderView getViewfinderHolder() { return (viewfinderView == null) ? (ViewfinderView) findViewById(R.id.viewfinder_view) : viewfinderView; } @Override public void dealDecode(Result rawResult, Bitmap barcode, float scaleFactor) { Log.i(TAG, "dealDecode ~~~~~ " + rawResult.getText() + " " + barcode + " " + scaleFactor); playBeepSoundAndVibrate(); Toast.makeText(this, rawResult.getText(), Toast.LENGTH_LONG).show();// 对此次扫描结果不满意可以调用// reScan(); }}
自定义AutoScannerView的实现
/** * Created by yangxixi on 16/11/22. * * 自动上下扫描 */public class AutoScannerView extends View { private static final String TAG = AutoScannerView.class.getSimpleName(); private Paint maskPaint; private Paint linePaint; private Paint traAnglePaint; private Paint textPaint; private CameraManager cameraManager; private final int maskColor = Color.parseColor("#60000000"); //蒙在摄像头上面区域的半透明颜色 private final int triAngleColor = Color.parseColor("#76EE00"); //边角的颜色 private final int lineColor = Color.parseColor("#FF0000"); //中间线的颜色 private final int textColor = Color.parseColor("#CCCCCC"); //文字的颜色 private final int triAngleLength = dp2px(20); //每个角的点距离 private final int triAngleWidth = dp2px(4); //每个角的点宽度 private final int textMarinTop = dp2px(30); //文字距离识别框的距离 private int lineOffsetCount = 0; public AutoScannerView(Context context, AttributeSet attrs) { super(context, attrs); maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); maskPaint.setColor(maskColor); traAnglePaint = new Paint(Paint.ANTI_ALIAS_FLAG); traAnglePaint.setColor(triAngleColor); traAnglePaint.setStrokeWidth(triAngleWidth); traAnglePaint.setStyle(Paint.Style.STROKE); linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); linePaint.setColor(lineColor); textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); textPaint.setColor(textColor); textPaint.setTextSize(dp2px(14)); } public void setCameraManager(CameraManager cameraManager) { this.cameraManager = cameraManager; invalidate();//重新进入可能不刷新,所以调用一次。 } @Override protected void onDraw(Canvas canvas) { if (cameraManager == null) return; Rect frame = cameraManager.getFramingRect(); Rect previewFrame = cameraManager.getFramingRectInPreview(); if (frame == null || previewFrame == null) { return; } int width = canvas.getWidth(); int height = canvas.getHeight(); // 除了中间的识别区域,其他区域都将蒙上一层半透明的图层 canvas.drawRect(0, 0, width, frame.top, maskPaint); canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, maskPaint); canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, maskPaint); canvas.drawRect(0, frame.bottom + 1, width, height, maskPaint); String text = "将二维码放入框内,即可自动扫描"; canvas.drawText(text, (width - textPaint.measureText(text)) / 2, frame.bottom + textMarinTop, textPaint); // 四个角落的三角 Path leftTopPath = new Path(); leftTopPath.moveTo(frame.left + triAngleLength, frame.top + triAngleWidth / 2); leftTopPath.lineTo(frame.left + triAngleWidth / 2, frame.top + triAngleWidth / 2); leftTopPath.lineTo(frame.left + triAngleWidth / 2, frame.top + triAngleLength); canvas.drawPath(leftTopPath, traAnglePaint); Path rightTopPath = new Path(); rightTopPath.moveTo(frame.right - triAngleLength, frame.top + triAngleWidth / 2); rightTopPath.lineTo(frame.right - triAngleWidth / 2, frame.top + triAngleWidth / 2); rightTopPath.lineTo(frame.right - triAngleWidth / 2, frame.top + triAngleLength); canvas.drawPath(rightTopPath, traAnglePaint); Path leftBottomPath = new Path(); leftBottomPath.moveTo(frame.left + triAngleWidth / 2, frame.bottom - triAngleLength); leftBottomPath.lineTo(frame.left + triAngleWidth / 2, frame.bottom - triAngleWidth / 2); leftBottomPath.lineTo(frame.left + triAngleLength, frame.bottom - triAngleWidth / 2); canvas.drawPath(leftBottomPath, traAnglePaint); Path rightBottomPath = new Path(); rightBottomPath.moveTo(frame.right - triAngleLength, frame.bottom - triAngleWidth / 2); rightBottomPath.lineTo(frame.right - triAngleWidth / 2, frame.bottom - triAngleWidth / 2); rightBottomPath.lineTo(frame.right - triAngleWidth / 2, frame.bottom - triAngleLength); canvas.drawPath(rightBottomPath, traAnglePaint); //循环划线,从上到下 if (lineOffsetCount > frame.bottom - frame.top - dp2px(10)) { lineOffsetCount = 0; } else { lineOffsetCount = lineOffsetCount + 6;// canvas.drawLine(frame.left, frame.top + lineOffsetCount, frame.right, frame.top + lineOffsetCount, linePaint); //画一条红色的线 Rect lineRect = new Rect(); lineRect.left = frame.left; lineRect.top = frame.top + lineOffsetCount; lineRect.right = frame.right; lineRect.bottom = frame.top + dp2px(10) + lineOffsetCount; canvas.drawBitmap(((BitmapDrawable)(getResources().getDrawable(R.drawable.scanline))).getBitmap(), null, lineRect, linePaint); } postInvalidateDelayed(10L, frame.left, frame.top, frame.right, frame.bottom); } private int dp2px(int dp) { float density = getContext().getResources().getDisplayMetrics().density; return (int) (dp * density + 0.5f); }}
集成之后,基本就可以,如果需要设置横屏竖屏直接设置screenOrientation就好了,里面的效果适配效果都已经实现;直接在dealDecode中处理扫描之后的结果,playBeepSoundAndVibrate可以设置响铃,振动或者同时都可以。想设置微信识别框的参数可以再AutoScannerView中修改,这里就不精细去实现哒
结语
到这里,大致流程就介绍完了。有什么不足的,欢迎指出。
欢迎在下方评论和喜欢,谢谢,转载请说明出处。
具体示例,请跳转Github查看,地址:https://github.com/yangxixi88/ZxingLite 欢迎StarStarStar啊~~~
本文章是从本人简书完整挪过来的,详情请参见本人简书地址:http://www.jianshu.com/users/f5b307af2a0d/latest_articles
读完思考
自定义AutoScannerView是匀速从上到下,而细细观察微信的效果,是两头慢,中间快,如果所以实现微信那种效果,需要从哪些方面改进呢,欢迎讨论~~
- Android二维码(仿微信,轻量Zxing)
- Android实现二维码扫描(仿微信,轻量Zxing)
- Android 二维码扫描基于Google Zxing(仿微信)
- Zxing二维码扫描(Android开源库)
- Android二维码开发(基于Zxing)
- android 二维码zxing开发
- Android ZXing 二维码
- android 二维码 google ZXing
- android zxing二维码横屏改竖屏
- Android二维码讲解(ZXing)
- Android之zxing二维码
- Android zxing生成二维码
- Android之二维码zxing
- android 二维码 Zxing记录
- Android二维码之zxing
- Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果 (转载)
- Android Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
- Android-扫描二维码、生成二维码(Zxing库)
- 修改web应用的部署应用名称
- Android 百度定位及地图SDK
- java项目打成jar包并上传服务器运行
- Ubuntu14.04配置caffe,及mnist数据集训练与测试(仅在CPU下)
- CSS:使用float实现水平布局、块级元素不换行
- Android二维码(仿微信,轻量Zxing)
- iServer 8C(2017)新增BaiduREST服务接口说明
- 2016JAVA宝典初级面试题(二)
- Iptables 详解
- solr实践(2)-- Solr6.2.0从Mysql上导入数据
- arcgis api for js入门开发系列六地图分屏对比(含源代码)
- iOS-2016年12月最新邓白氏编码申请流程,一步一步教会你(超全)
- 生成jar包命令
- R语言做柱状图