Android扫描名片的动画以及剪裁扫描框的图片

2024-09-07 12:48

本文主要是介绍Android扫描名片的动画以及剪裁扫描框的图片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考代码:https://github.com/smartown/CertificateCamera

本文章在上述参考代码的基础上进行修改,用到的SurfaceView是链接代码里的CameraPreview,不过本人比较懒,直接加入相机连续对焦模式代替点击屏幕对焦   ,在CameraPreview中添加

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续对焦模式

即可。

布局文件:

主要是用半透明的view将中间的扫描框包围其起来

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000"><com.view.CameraPreviewandroid:id="@+id/camera_surface"android:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:orientation="vertical"><Viewandroid:id="@+id/viewtop"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="@color/preview_mock" /><!--android:background="#5e9" />--><!--android:background="@color/preview_mock" />--><LinearLayoutandroid:id="@+id/camera_crop_container"android:layout_width="0dp"android:layout_height="0dp"android:orientation="horizontal"><Viewandroid:id="@+id/viewleft"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@color/preview_mock" /><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"><ImageViewandroid:id="@+id/camera_crop"android:layout_width="0dp"android:layout_height="0dp"android:scaleType="fitXY" /><ImageViewandroid:id="@+id/iv_scan_line"android:layout_width="200dp"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_centerHorizontal="true"android:maxHeight="250dp"android:src="@mipmap/face_scan_line"android:visibility="gone"/></RelativeLayout><RelativeLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:background="@color/preview_mock"><Viewandroid:id="@+id/viewright"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/></RelativeLayout></LinearLayout></LinearLayout><TextViewandroid:id="@+id/tv_picture"android:layout_width="match_parent"android:layout_height="136dp"android:layout_gravity="right"android:gravity="center"android:text="拍照"android:textColor="@color/c_white"android:background="@color/preview_mock"/></LinearLayout><!-- 顶部 --><include layout="@layout/toolbar_right"/><com.view.RotateTextViewandroid:id="@+id/rtv_scaning"android:layout_width="wrap_content"android:layout_height="match_parent"android:textSize="@dimen/sp_14"android:textColor="@color/c_B5B5B5"android:layout_alignParentRight="true"android:gravity="center_vertical"android:layout_centerVertical="true"android:visibility="gone"android:text="识别中"/></RelativeLayout>

在activity中我的改动比较大,由于我只扫描名片不涉及到横屏竖屏切换,所以页面强制竖屏,初始化代码如下,关于权限申请本文章不进行展示了,

private void init() {//获取屏幕最小边,设置为cameraSurface较窄的一边float screenMinSize = Math.min(getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().heightPixels);//根据screenMinSize,计算出cameraSurface的较宽的一边,长宽比为标准的16:9float maxSize = screenMinSize / 9.0f * 16.0f;RelativeLayout.LayoutParams layoutParams;layoutParams = new RelativeLayout.LayoutParams((int) screenMinSize, (int) maxSize);layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);cameraSurface.setLayoutParams(layoutParams);float width = (int) (screenMinSize * 0.65);float height = (int) (width * 43.0f / 30.0f);LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) height);RelativeLayout.LayoutParams cropParams = new RelativeLayout.LayoutParams((int) width, (int) height);containerView.setLayoutParams(containerParams);cropView.setLayoutParams(cropParams);cropView.setImageResource(R.mipmap.face_scan_rect_blue);ivScanLine.setMaxHeight(cropView.getHeight());Display defaultDisplay = getWindowManager().getDefaultDisplay();Point point = new Point();defaultDisplay.getSize(point);int x = point.x;int y = point.y;Log.i(TAG, "x = " + x + ",y = " + y);}

点击拍照后的处理,主要是剪裁与扫描框相同大小的区域:

 cameraSurface.takePhoto(new Camera.PictureCallback() {@Overridepublic void onPictureTaken(final byte[] data, Camera camera) {camera.stopPreview();ivScanLine.setVisibility(View.VISIBLE);rtvScaning.setVisibility(View.VISIBLE);//子线程处理图片,防止ANRnew Thread(new Runnable() {@Overridepublic void run() {try {File originalFile = getOriginalFile();FileOutputStream originalFileOutputStream = new FileOutputStream(originalFile);originalFileOutputStream.write(data);originalFileOutputStream.close();Bitmap bitmap = BitmapFactory.decodeFile(originalFile.getPath());//计算裁剪位置float left, top, right, bottom;left = ((float) containerView.getLeft() - (float) cameraSurface.getLeft()) / (float) cameraSurface.getWidth();top = (float) cropView.getTop() / (float) cameraSurface.getHeight();right = (float) containerView.getRight() / (float) cameraSurface.getWidth();bottom = (float) cropView.getBottom() / (float) cameraSurface.getHeight();//裁剪及保存到文件int w = cropView.getMeasuredWidth();int h = cropView.getMeasuredHeight();cropView.getLocationOnScreen(location);// 获取状态栏高度Rect frame = new Rect();ScanCardActivity.this.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);int statusBarHeight = frame.top;System.out.println(statusBarHeight);Bitmap cropBitmap;//判断照片是横屏还是竖屏if ( bitmap.getWidth()> bitmap.getHeight()){int  lx;if (Utils.checkDeviceHasNavigationBar2(ScanCardActivity.this)){lx =viewtop.getHeight()-statusBarHeight+NavUtils.getNavigationBarHeight(ScanCardActivity.this);}else{lx=viewtop.getHeight()-statusBarHeight;}int   ly=bitmap.getHeight()- cropView.getWidth()-viewleft.getWidth();//判断剪裁范围是否超出照片范围if ((lx+cropView.getHeight())>bitmap.getWidth()||(ly+cropView.getWidth())>bitmap.getHeight()){cropBitmap=bitmap;}else{cropBitmap = Bitmap.createBitmap(bitmap,(int) lx,(int) ly,(int) cropView.getHeight(),(int) cropView.getWidth());}}else{int lx2;if (Utils.checkDeviceHasNavigationBar2(ScanCardActivity.this)){lx2=viewtop.getHeight()-statusBarHeight+NavUtils.getNavigationBarHeight(ScanCardActivity.this);}else{lx2=viewtop.getHeight()-statusBarHeight;}//判断剪裁范围是否超出照片范围if ((viewleft.getWidth()+w)>bitmap.getWidth()||(lx2+h)>bitmap.getHeight()){cropBitmap=bitmap;}else{cropBitmap = Bitmap.createBitmap(bitmap,(int) viewleft.getWidth(),(int)lx2,(int)  w,(int)h);}}final File cropFile = getCropFile();BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(cropFile));cropBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);bos.flush();bos.close();Handler mainHandler = new Handler(Looper.getMainLooper());mainHandler.post(new Runnable() {@Overridepublic void run() {//已在主线程中,可以更新UIpostImageCard(cropFile);}});runOnUiThread(new Runnable() {@Overridepublic void run() {
//                                        resultView.setVisibility(View.VISIBLE);}});return;} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}runOnUiThread(new Runnable() {@Overridepublic void run() {
//                                optionView.setVisibility(View.VISIBLE);cameraSurface.setEnabled(true);}});}}).start();Loger.debug("Bitmap  containerView.getWidth()  :  " + containerView.getWidth());Loger.debug("Bitmap  containerView.getHeight()  :  " + containerView.getHeight());TranslateAnimation translateAni = new TranslateAnimation(//X轴初始位置Animation.ABSOLUTE, 0.0f,//X轴移动的结束位置Animation.ABSOLUTE, 0.0f,//y轴开始位置Animation.ABSOLUTE, 0.0f,//y轴移动后的结束位置Animation.ABSOLUTE, containerView.getHeight());//                Animation.RELATIVE_TO_PARENT,  containerView.getX(), Animation.RELATIVE_TO_PARENT,
//                        containerView.getX()+containerView.getWidth(), Animation.RELATIVE_TO_PARENT, containerView.getY(),
//                        Animation.RELATIVE_TO_PARENT, containerView.getY()//                );//设置动画执行的时间,单位是毫秒translateAni.setDuration(3000);// 设置动画重复次数// -1或者Animation.INFINITE表示无限重复,正数表示重复次数,0表示不重复只播放一次translateAni.setRepeatCount(10);// 设置动画模式(Animation.REVERSE设置循环反转播放动画,Animation.RESTART每次都从头开始)translateAni.setRepeatMode(Animation.REVERSE);translateAni.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {ivScanLine.setVisibility(View.GONE);}@Overridepublic void onAnimationRepeat(Animation animation) {}});// 启动动画ivScanLine.startAnimation(translateAni);}});

主要修改就是剪裁图片的时候,要区别拍照后是横向图片还是竖向照片,然后为了防止有没有测试到的情况直接检测裁剪的范围是否超过了原图,加入了长宽与原图的判断,在最后运行扫描条来回移动的动画。

基本的修改就这些了,最后在handler中放入获取剪裁图片后的下一步处理。

本文暂时用于自己日后参考,可能会有些代码不全的地方

 

 

 

这篇关于Android扫描名片的动画以及剪裁扫描框的图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145105

相关文章

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

Java实现数据库图片上传与存储功能

《Java实现数据库图片上传与存储功能》在现代的Web开发中,上传图片并将其存储在数据库中是常见的需求之一,本文将介绍如何通过Java实现图片上传,存储到数据库的完整过程,希望对大家有所帮助... 目录1. 项目结构2. 数据库表设计3. 实现图片上传功能3.1 文件上传控制器3.2 图片上传服务4. 实现

Java实现数据库图片上传功能详解

《Java实现数据库图片上传功能详解》这篇文章主要为大家详细介绍了如何使用Java实现数据库图片上传功能,包含从数据库拿图片传递前端渲染,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、前言2、数据库搭建&nbsChina编程p; 3、后端实现将图片存储进数据库4、后端实现从数据库取出图片给前端5、前端拿到

Android WebView无法加载H5页面的常见问题和解决方法

《AndroidWebView无法加载H5页面的常见问题和解决方法》AndroidWebView是一种视图组件,使得Android应用能够显示网页内容,它基于Chromium,具备现代浏览器的许多功... 目录1. WebView 简介2. 常见问题3. 网络权限设置4. 启用 JavaScript5. D

Android如何获取当前CPU频率和占用率

《Android如何获取当前CPU频率和占用率》最近在优化App的性能,需要获取当前CPU视频频率和占用率,所以本文小编就来和大家总结一下如何在Android中获取当前CPU频率和占用率吧... 最近在优化 App 的性能,需要获取当前 CPU视频频率和占用率,通过查询资料,大致思路如下:目前没有标准的

Python使用PIL库将PNG图片转换为ICO图标的示例代码

《Python使用PIL库将PNG图片转换为ICO图标的示例代码》在软件开发和网站设计中,ICO图标是一种常用的图像格式,特别适用于应用程序图标、网页收藏夹图标等场景,本文将介绍如何使用Python的... 目录引言准备工作代码解析实践操作结果展示结语引言在软件开发和网站设计中,ICO图标是一种常用的图像