本文主要是介绍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扫描名片的动画以及剪裁扫描框的图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!