Android 最简单的自定义证件照Mask之一
生活随笔
收集整理的這篇文章主要介紹了
Android 最简单的自定义证件照Mask之一
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
作者: Jooyer, 時間: 2019.01.08
Github地址,歡迎點贊,fork
現在部分APP都有一個身份認證,一般需要身份證正面,反面,在度娘那也有很多,我發現他們在屬性配置上略少了一些,所以特意寫了一個!,四周線條顏色,間距,粗細都有屬性設置!
本次代碼也是比較簡單,就一個系統的 SurfaceView 和 一個自定義的View, 我就直接貼源碼,如果還有不清楚的,可以留言或者看github
接下來我們依次講解:
首先,看看 CameraSufaceView,必要的注釋都有
package cn.molue.jooyer.masker;import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.Rect; import android.hardware.Camera; import android.os.Environment; import android.support.constraint.ConstraintLayout; import android.util.AttributeSet; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Toast;import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import java.util.List;/*** @Date 2018/12/29* @Desc 相機預覽界面*/ public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback {private static final String TAG = "CameraSurfaceView";private SurfaceHolder holder;private Camera mCamera;private Rect mCenterMarkRect;private int mScreenWidth;private int mScreenHeight;private File mFile;private OnPathChangedListener onPathChangedListener;public void setOnPathChangedListener(OnPathChangedListener onPathChangedListener) {this.onPathChangedListener = onPathChangedListener;}public CameraSurfaceView(Context context) {this(context, null);}public CameraSurfaceView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CameraSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);getScreenMetrix(context);initView();}//拿到手機屏幕大小private void getScreenMetrix(Context context) {mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;mScreenHeight = context.getResources().getDisplayMetrics().heightPixels;}private void initView() {//獲得surfaceHolder引用holder = getHolder();// 屏幕常亮holder.setKeepScreenOn(true);//為SurfaceView的句柄添加一個回調函數holder.addCallback(this);// holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//設置類型}// 在surface創建后立即被調用。在開發自定義相機時,可以通過重載這個函數調用camera.open()、camera.setPreviewDisplay(),// 來實現獲取相機資源、連接camera和surface等操作public void surfaceCreated(SurfaceHolder holder) {Log.i(TAG, "surfaceCreated");if (mCamera == null) {mCamera = Camera.open();try {// 設置用于顯示拍照影像的SurfaceHolder對象mCamera.setPreviewDisplay(holder);} catch (IOException e) {e.printStackTrace();}}}// 可以通過重載這個函數調用camera.startPreview來開啟相機預覽,使得camera預覽幀數據可以傳遞給surface,從而實時顯示相機預覽圖像public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {setCameraParams(mScreenWidth, mScreenHeight);mCamera.startPreview();}public void surfaceDestroyed(SurfaceHolder holder) {mCamera.stopPreview();//停止預覽mCamera.release();//釋放相機資源mCamera = null;}public void onAutoFocus(boolean success, Camera Camera) {}private void setCameraParams(int width, int height) {Log.i(TAG, "------setCameraParams width=" + width + " height=" + height);Camera.Parameters parameters = mCamera.getParameters();// 獲取攝像頭支持的PictureSize列表List<Camera.Size> pictureSizeList = parameters.getSupportedPictureSizes();/**從列表中選取合適的分辨率*/Camera.Size picSize = getProperSize(pictureSizeList, ((float) height / width));if (null == picSize) {Log.i(TAG, "null == picSize");picSize = parameters.getPictureSize();}// 根據選出的PictureSize重新設置SurfaceView大小float w = picSize.width;float h = picSize.height;Log.i(TAG, "----------picSize.width=" + picSize.width + " --- picSize.height=" + picSize.height);// 設置捕獲圖片尺寸parameters.setPictureSize(picSize.width, picSize.height);this.setLayoutParams(new ConstraintLayout.LayoutParams((int) (height * (h / w)), height));// 獲取攝像頭支持的PreviewSize列表List<Camera.Size> previewSizeList = parameters.getSupportedPreviewSizes();Camera.Size preSize = getProperSize(previewSizeList, ((float) height) / width);if (null != preSize) {Log.i(TAG, "----------preSize.width=" + preSize.width + " --- preSize.height=" + preSize.height);// 設置預覽圖片尺寸parameters.setPreviewSize(preSize.width, preSize.height);}parameters.setJpegQuality(100); // 設置照片質量if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 連續對焦模式}mCamera.cancelAutoFocus();//自動對焦。mCamera.setParameters(parameters);// 計算攝像頭方向Camera.CameraInfo info =new Camera.CameraInfo();Camera.getCameraInfo(0, info);int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();int degrees = 0;switch (rotation) {case Surface.ROTATION_0:degrees = 0;break;case Surface.ROTATION_90:degrees = 90;break;case Surface.ROTATION_180:degrees = 180;break;case Surface.ROTATION_270:degrees = 270;break;}int result;if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {result = (info.orientation + degrees) % 360;result = (360 - result) % 360; // compensate the mirror} else { // back-facingresult = (info.orientation - degrees + 360) % 360;}// 設置PreviewDisplay的方向,效果就是將捕獲的畫面旋轉多少度顯示mCamera.setDisplayOrientation(result);}/*** 從列表中選取合適的分辨率* 默認w:h = 4:3* <p>注意:這里的w對應屏幕的height* h對應屏幕的width<p/>*/private Camera.Size getProperSize(List<Camera.Size> pictureSizeList, float screenRatio) {Log.i(TAG, "screenRatio=" + screenRatio);Camera.Size result = null;for (Camera.Size size : pictureSizeList) {float currentRatio = ((float) size.width) / size.height;if (currentRatio - screenRatio == 0) {result = size;break;}}if (null == result) {for (Camera.Size size : pictureSizeList) {float curRatio = ((float) size.width) / size.height;if (curRatio == 4f / 3) {// 默認w:h = 4:3result = size;break;}}}return result;}// 拍照瞬間調用 (添加這個才會有咔嚓聲)private Camera.ShutterCallback shutter = new Camera.ShutterCallback() {public void onShutter() {}};// 獲得沒有壓縮過的圖片數據private Camera.PictureCallback raw = new Camera.PictureCallback() {public void onPictureTaken(byte[] data, Camera Camera) {}};//創建jpeg圖片回調數據對象private Camera.PictureCallback jpeg = new Camera.PictureCallback() {private Bitmap bitmap;public void onPictureTaken(byte[] data, Camera Camera) {BufferedOutputStream bos = null;Bitmap bm = null;if (data != null) {}try {// 獲得圖片bm = BitmapFactory.decodeByteArray(data, 0, data.length);if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {// 圖片存儲前旋轉Matrix m = new Matrix();int height = bm.getHeight();int width = bm.getWidth();m.setRotate(90);//旋轉后的圖片bitmap = Bitmap.createBitmap(bm, 0, 0, width, height, m, true);String photo = "IMMQY/IMG_" + String.valueOf(new Date().getTime() + ".jpg");mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(), photo);if (!mFile.getParentFile().exists()) {mFile.getParentFile().mkdirs();}bos = new BufferedOutputStream(new FileOutputStream(mFile));if (null == mCenterMarkRect) {throw new NullPointerException("mCenterMarkRect is not null");}Bitmap sizeBitmap = Bitmap.createScaledBitmap(bitmap,mScreenWidth, mScreenHeight, true);// 截取bm = Bitmap.createBitmap(sizeBitmap,mCenterMarkRect.left, mCenterMarkRect.top,mCenterMarkRect.right - mCenterMarkRect.left,mCenterMarkRect.bottom - mCenterMarkRect.top);bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//將圖片壓縮到流中} else {Toast.makeText(getContext(), "沒有檢測到內存卡", Toast.LENGTH_SHORT).show();}} catch (Exception e) {e.printStackTrace();} finally {try {bos.flush();//輸出bos.close();//關閉bm.recycle();// 回收bitmap空間mCamera.stopPreview();// 關閉預覽mCamera.startPreview();// 開啟預覽if (onPathChangedListener != null) {onPathChangedListener.onValueChange(mFile.getPath());}} catch (IOException e) {e.printStackTrace();}}}};/*** 拍照*/public void takePicture() {//設置參數,并拍照setCameraParams(mScreenWidth, mScreenHeight);// 當調用camera.takePiture方法后,camera關閉了預覽,這時需要調用startPreview()來重新開啟預覽mCamera.takePicture(shutter, null, jpeg);}public void setAutoFocus() {mCamera.autoFocus(this);}public void setCenterMarkRect(Rect centerMarkRect) {this.mCenterMarkRect = centerMarkRect;}public interface OnPathChangedListener {void onValueChange(String path);}}復制代碼然后我們來瞧瞧 CameraMaskView ,其實這里就是將四周擋住,留下中間位置作為拍照的具體內容
package cn.molue.jooyer.masker;import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View;/*** @Date 2018/12/29* @Time 11:37*/ public class CameraMaskView extends View {// 默認如果方框布局中時距離上面尺寸private static final int MASK_MARGIN = 100;// 默認線寬private static final int LINE_WIDTH = 5;// 默認線長private static final int LINE_LENGTH = 40;// 默認線外邊距private static final int LINE_MARGIN = 10;// 默認線內邊距private static final int LINE_PADDING = 5;// 默認提示文本private static final String TEXT = "請將身份證置于此框內";// 控件的寬高private int viewWidth;private int viewHeight;// 中間透明區域(方框)寬高public int rectWidth;public int rectHeight;// 提示文本private String mTipText = "";// 文本顏色private int mTipTextColor = 0;// 文本大小private int mTipTextSize = 0;// 文本距離底部 遮罩框 間隔private int mTipMargin = 0;// 中間透明區域(方框)坐標private Rect mCenterMarkRect = new Rect();// 遮罩顏色private int mMaskColor = 0;// 遮罩是居中,還是居上private int mMaskPosition = 0;private int mMaskMargin = 0;// 四周線條長度private int mLineLength;// 四周線條寬度(厚度)private int mLineWidth;private int mLineColor = 0;private int mLinePadding = 0;private int mLineMargin = 0;// 文字畫筆private Paint maskPaint;// 線條畫筆private Paint linePaint;// 文字畫筆private Paint wordPaint;// 計算提示文本的位置的private Rect rect;// 文本基線private int baseline;public CameraMaskView(Context context, AttributeSet attrs) {super(context, attrs);parse(context, attrs);init(context);}private void parse(Context context, AttributeSet attrs) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CameraMaskView);mMaskMargin = (int) array.getDimension(R.styleable.CameraMaskView_cmv_mask_margin, MASK_MARGIN);mMaskPosition = array.getInt(R.styleable.CameraMaskView_cmv_position_flag, 0);mMaskColor = array.getColor(R.styleable.CameraMaskView_cmv_mask_color, 0xa0000000);mTipText = array.getString(R.styleable.CameraMaskView_cmv_tip_text);if (null == mTipText || mTipText.isEmpty()) {mTipText = TEXT;}mTipTextColor = array.getColor(R.styleable.CameraMaskView_cmv_tip_color, 0xFFFFFFFF);mTipTextSize = (int) array.getDimension(R.styleable.CameraMaskView_cmv_tip_size, sp2px(context, 14));mTipMargin = (int) array.getDimension(R.styleable.CameraMaskView_cmv_tip_margin, dp2px(context, 20));mLineColor = array.getColor(R.styleable.CameraMaskView_cmv_line_color, 0xFF85D28A);mLineWidth = (int) array.getDimension(R.styleable.CameraMaskView_cmv_line_width, dp2px(context, LINE_WIDTH));mLineLength = (int) array.getDimension(R.styleable.CameraMaskView_cmv_line_length, dp2px(context, LINE_LENGTH));mLinePadding = (int) array.getDimension(R.styleable.CameraMaskView_cmv_line_padding, dp2px(context, LINE_PADDING));mLineMargin = (int) array.getDimension(R.styleable.CameraMaskView_cmv_line_margin, dp2px(context, LINE_MARGIN));array.recycle();}private void init(Context context) {viewWidth = context.getResources().getDisplayMetrics().widthPixels;viewHeight = context.getResources().getDisplayMetrics().heightPixels;rectWidth = viewWidth - dp2px(context, 2 * mLineMargin);// 身份證 長度85.6mm,寬度54mmrectHeight = (int) (rectWidth * 54 / 85.6);if (1 == mMaskPosition) {mCenterMarkRect.left = (viewWidth - rectWidth) / 2;mCenterMarkRect.top = mMaskMargin;mCenterMarkRect.right = mCenterMarkRect.left + rectWidth;mCenterMarkRect.bottom = mMaskMargin + rectHeight;} else {mCenterMarkRect.left = (viewWidth - rectWidth) / 2;mCenterMarkRect.top = (viewHeight - rectHeight) / 2;mCenterMarkRect.right = mCenterMarkRect.left + rectWidth;mCenterMarkRect.bottom = mCenterMarkRect.top + rectHeight;}linePaint = new Paint();linePaint.setAntiAlias(true);linePaint.setColor(mLineColor);linePaint.setStyle(Paint.Style.STROKE);linePaint.setStrokeWidth(mLineWidth);// 設置線寬linePaint.setAlpha(255);maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);maskPaint.setColor(mMaskColor);wordPaint = new Paint(Paint.ANTI_ALIAS_FLAG);wordPaint.setColor(mTipTextColor);wordPaint.setTextSize(mTipTextSize);rect = new Rect(mCenterMarkRect.left, mCenterMarkRect.top - mTipTextSize - mTipMargin,mCenterMarkRect.right, mCenterMarkRect.top - mTipMargin);Paint.FontMetricsInt fontMetrics = wordPaint.getFontMetricsInt();baseline = rect.top + (rect.bottom - rect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;wordPaint.setTextAlign(Paint.Align.CENTER);}public void onDraw(Canvas canvas) {super.onDraw(canvas);if (1 == mMaskPosition) {// 頂部蒙層canvas.drawRect(0, 0, viewWidth, mMaskMargin, maskPaint);// 左側canvas.drawRect(0, mMaskMargin, (viewWidth - rectWidth) / 2, mMaskMargin + rectHeight, maskPaint);// 右側canvas.drawRect(viewWidth - (viewWidth - rectWidth) / 2, mMaskMargin, viewWidth, mMaskMargin + rectHeight, maskPaint);// 底部蒙層canvas.drawRect(0, mMaskMargin + rectHeight, viewWidth, viewHeight, maskPaint);} else {// 頂部蒙層canvas.drawRect(0, 0, viewWidth, viewHeight / 2 - rectHeight / 2, maskPaint);// 左側canvas.drawRect(0, viewHeight / 2 - rectHeight / 2, (viewWidth - rectWidth) / 2, viewHeight / 2 + rectHeight / 2, maskPaint);// 右側canvas.drawRect(viewWidth - (viewWidth - rectWidth) / 2, viewHeight / 2 - rectHeight / 2, viewWidth, viewHeight / 2 + rectHeight / 2, maskPaint);// 底部蒙層canvas.drawRect(0, viewHeight / 2 + rectHeight / 2, viewWidth, viewHeight, maskPaint);}// 繪制文字canvas.drawText(mTipText, rect.centerX(), baseline, wordPaint);// 繪制四個角canvas.drawLine(mCenterMarkRect.left - dp2px(getContext(), mLinePadding) - mLineWidth / 2.0F, mCenterMarkRect.top - dp2px(getContext(), mLinePadding),mCenterMarkRect.left + mLineLength, mCenterMarkRect.top - dp2px(getContext(), mLinePadding), linePaint);canvas.drawLine(mCenterMarkRect.left - dp2px(getContext(), mLinePadding), mCenterMarkRect.top - dp2px(getContext(), mLinePadding),mCenterMarkRect.left - dp2px(getContext(), mLinePadding), mCenterMarkRect.top + mLineLength, linePaint);canvas.drawLine(mCenterMarkRect.right - mLineLength, mCenterMarkRect.top - dp2px(getContext(), mLinePadding),mCenterMarkRect.right + dp2px(getContext(), mLinePadding) + mLineWidth / 2.0F, mCenterMarkRect.top - dp2px(getContext(), mLinePadding), linePaint);canvas.drawLine(mCenterMarkRect.right + dp2px(getContext(), mLinePadding), mCenterMarkRect.top - dp2px(getContext(), mLinePadding),mCenterMarkRect.right + dp2px(getContext(), mLinePadding), mCenterMarkRect.top + mLineLength, linePaint);canvas.drawLine(mCenterMarkRect.left - dp2px(getContext(), mLinePadding), mCenterMarkRect.bottom - mLineLength,mCenterMarkRect.left - dp2px(getContext(), mLinePadding), mCenterMarkRect.bottom + dp2px(getContext(), mLinePadding) + mLineWidth / 2.0F, linePaint);canvas.drawLine(mCenterMarkRect.left - dp2px(getContext(), mLinePadding), mCenterMarkRect.bottom + dp2px(getContext(), mLinePadding),mCenterMarkRect.left + mLineLength, mCenterMarkRect.bottom + dp2px(getContext(), mLinePadding), linePaint);canvas.drawLine(mCenterMarkRect.right - mLineLength, mCenterMarkRect.bottom + dp2px(getContext(), mLinePadding),mCenterMarkRect.right + dp2px(getContext(), mLinePadding) + mLineWidth / 2.0F, mCenterMarkRect.bottom + dp2px(getContext(), mLinePadding), linePaint);canvas.drawLine(mCenterMarkRect.right + dp2px(getContext(), mLinePadding), mCenterMarkRect.bottom - mLineLength,mCenterMarkRect.right + dp2px(getContext(), mLinePadding), mCenterMarkRect.bottom + dp2px(getContext(), mLinePadding), linePaint);}public Rect getCenterMarkRect() {return mCenterMarkRect;}private int dp2px(Context context, float dpValue) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());}private int sp2px(Context context, int dpValue) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dpValue, context.getResources().getDisplayMetrics());}} 復制代碼來看看自定義的屬性(xml文件)
里面就是一大堆自定義的屬性,具體含義往下看
xml version="1.0" encoding="utf-8" <resources><declare-styleable name="CameraMaskView"><!-- 蒙層顏色 --><attr name="cmv_mask_color" format="color|reference" /><!-- 提示文本 --><attr name="cmv_tip_text" format="string|reference" /><!-- 文字顏色 --><attr name="cmv_tip_color" format="color|reference" /><!-- 文字大小 --><attr name="cmv_tip_size" format="integer|dimension" /><!-- 文字底部距離方框的間隔 --><attr name="cmv_tip_margin" format="integer|dimension" /><!-- 邊線顏色 --><attr name="cmv_line_color" format="color|reference" /><!-- 邊線寬度(厚度) --><attr name="cmv_line_width" format="integer|dimension" /><!-- 邊線長度 --><attr name="cmv_line_length" format="integer|dimension" /><!-- 邊線與內部透明方框的間隔 --><attr name="cmv_line_padding" format="integer|dimension" /><!-- 邊線與外面手機屏幕邊框的間隔 --><attr name="cmv_line_margin" format="integer|dimension"/><!-- 默認方框是劇中的 --><attr name="cmv_position_flag"><enum name="center" value="0"/><enum name="margin" value="1"/></attr><!-- 只有當設置了 cmv_position_flag = margin 才有效 --><attr name="cmv_mask_margin" format="integer|dimension"/></declare-styleable></resources> 復制代碼屬性雖然有些多,但是大都都見名知意.
最后來看看在 Activity 布局中的用法
xml version="1.0" encoding="utf-8" <android.support.constraint.ConstraintLayoutxmlns: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"tools:context=".CameraActivity"><cn.molue.jooyer.masker.CameraSurfaceViewandroid:id="@+id/camera_surface_view"android:layout_width="0dp"android:layout_height="0dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><cn.molue.jooyer.masker.CameraMaskViewandroid:id="@+id/camera_rect_view"android:layout_width="0dp"android:layout_height="0dp"app:cmv_line_color="#85D28A"app:cmv_line_length="40dp"app:cmv_line_margin="10dp"app:cmv_line_padding="2dp"app:cmv_line_width="2dp"app:cmv_mask_color="#FF76635A"app:cmv_mask_margin="80dp"app:cmv_position_flag="margin"app:cmv_tip_color="#FFFFFF"app:cmv_tip_margin="40dp"app:cmv_tip_size="15sp"app:cmv_tip_text="請將身份證頭像面置于此框內"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><Viewandroid:id="@+id/view_background"android:layout_width="0dp"android:layout_height="123dp"android:background="#FF2F2A28"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/><TextViewandroid:id="@+id/text_view_cancel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="33dp"android:layout_marginEnd="50dp"android:padding="18dp"android:gravity="center_vertical"android:text="取消"android:textColor="#FFF"android:textSize="14sp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintRight_toLeftOf="@id/image_view_take"/><ImageViewandroid:id="@+id/image_view_take"android:layout_width="60dp"android:layout_height="60dp"android:background="@drawable/camera_take_background"android:layout_marginBottom="30dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"/></android.support.constraint.ConstraintLayout> 復制代碼這個就不解釋了,最后看看 Activity中的操作
package cn.molue.jooyer.masker;import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;/*** @Author Jooyer* @Date 2018/01/08* @Time 14.27*/ public class CameraActivity extends AppCompatActivity {private CameraSurfaceView cameraSurfaceView;private CameraMaskView cameraRectView;private TextView tvCancel;private ImageView ivTake;protected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_camera);findView();initListener();}private void findView() {tvCancel = findViewById(R.id.text_view_cancel);ivTake = findViewById(R.id.image_view_take);cameraSurfaceView = findViewById(R.id.camera_surface_view);cameraRectView = findViewById(R.id.camera_rect_view);}public void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);// 設置中間預覽大小cameraSurfaceView.setCenterMarkRect(cameraRectView.getCenterMarkRect());}private void initListener() {tvCancel.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {finish();}});ivTake.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {cameraSurfaceView.takePicture();}});cameraSurfaceView.setOnPathChangedListener(new CameraSurfaceView.OnPathChangedListener() {public void onValueChange(String path) {Toast.makeText(CameraActivity.this, path, Toast.LENGTH_SHORT).show();}});} } 復制代碼記得在使用時申請相機和存儲權限
喜歡記得點贊,收藏,轉發哈!
參考地址: blog.csdn.net/github_3784… ,感謝大佬指引!
總結
以上是生活随笔為你收集整理的Android 最简单的自定义证件照Mask之一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 笔记本电脑怎样当无线服务器,笔记本当无线
- 下一篇: android sina oauth2.