Explain:
A simple requirement, the external shadow, the internal layout is transparent, and the camera is opened at the bottom (here only the layout code, click here with the camera).
Code:
1. Call
Just call in Activity, set the height and width of the middle area.
Activity code
private OcrFaceMaskSurfaceView surfaceview; surfaceview = (OcrFaceMaskSurfaceView) findViewById(R.id.surface_view); surfaceview.setMaskSize(900, 600);
Activity layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#EFEFF4" android:orientation="vertical" tools:context=".WebViewActivity"> <com.gxjl.pe.gxjlpesdk.view.OcrFaceMaskSurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" > </com.gxjl.pe.gxjlpesdk.view.OcrFaceMaskSurfaceView> </LinearLayout>
2. OcrFaceMaskSurfaceView.java is a custom canvas
Implementation ideas:
(1) Two layers of canvas in the custom layout. The first layer is just to start and load the camera
(2) The second layer draws the outer shadow and the inner transparency, plus the inner text
The code is as follows: (CameraHelper is a camera tool class, which can be commented out. Click here to see the complete code with camera + demo)
(3) UiUtil utility class- click here
(4) The code notes are very clear
package com.gxjl.pe.gxjlpesdk.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PixelFormat; import android.util.AttributeSet; import android.util.Log; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.FrameLayout; import com.gxjl.pe.gxjlpesdk.camrea.CameraHelper; import com.gxjl.pe.gxjlpesdk.util.UiUtil; public class OcrFaceMaskSurfaceView extends FrameLayout { private Context context; private MSurfaceView surfaceView;//Load mask for camera private MaskView maskView;//Load mask for layout private int width;//Screen width private int height;//Screen height private int maskWidth;//Middle transparent area width private int maskHeight;//Height of transparent area in the middle private int screenWidth;//Camera capture width private int screenHeight;//Camera capture height public OcrFaceMaskSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; surfaceView = new MSurfaceView(context);//The first layer of canvas is used to load the camera maskView = new MaskView(context);//The second layer of canvas is used to draw all the layouts this.addView(surfaceView, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); this.addView(maskView, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); screenHeight = display.getHeight(); screenWidth = display.getWidth(); CameraHelper.getInstance().setMaskSurfaceView(this); } public void setMaskSize(Integer width, Integer height) { maskHeight = height; maskWidth = width; } public int[] getMaskSize() { return new MaskSize().size; } private class MaskSize { private int[] size; private MaskSize() { this.size = new int[]; } } /** * Layout of the carrying camera */ private class MSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holder; public MSurfaceView(Context context) { super(context); this.holder = this.getHolder(); //Transparent transparent this.holder.setFormat(PixelFormat.TRANSPARENT); this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); this.holder.addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { width = w; height = h; CameraHelper.getInstance().openCamera(holder, format, width, height, screenWidth, screenHeight); } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { CameraHelper.getInstance().releaseCamera(); } } /** * All layout of mask layer */ private class MaskView extends View { private Paint linePaint; private Paint rectPaint; private Paint topTextPaint; private Paint bottomTextPaint; public MaskView(Context context) { super(context); //Paint the rectangle border of the transparent area in the middle linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); linePaint.setColor(Color.TRANSPARENT);//Set the middle area color to transparent linePaint.setStyle(Style.STROKE); linePaint.setStrokeWidth(3f); linePaint.setAlpha(0);//The value range is 0-255, the smaller the value, the more transparent //Draw rectangular shadow area around rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); rectPaint.setColor(Color.BLACK); rectPaint.setStyle(Style.FILL); rectPaint.setAlpha(170);//The value range is 0-255, the smaller the value, the more transparent //Draw top middle prompt font topTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); topTextPaint.setColor(Color.WHITE); //topTextPaint.setStyle(Paint.Style.FILL); topTextPaint.setTextAlign(Paint.Align.CENTER);//Put the x,y coordinates in the middle of the font (the default x,y coordinates are the font head) topTextPaint.setTextSize(UiUtil.sp2px(context, 14)); //Draw top middle prompt font bottomTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); bottomTextPaint.setColor(Color.parseColor("#A0A0A0")); //bottomTextPaint.setStyle(Paint.Style.FILL); bottomTextPaint.setTextAlign(Paint.Align.CENTER);//Put the x,y coordinates in the middle of the font (the default x,y coordinates are the font head) bottomTextPaint.setTextSize(UiUtil.sp2px(context, 12)); } @Override protected void onDraw(Canvas canvas) { if (maskHeight == 0 && maskWidth == 0) { return; } if (maskHeight == height || maskWidth == width) { return; } if ((height > width && maskHeight < maskWidth) || (height < width && maskHeight > maskWidth)) { int temp = maskHeight; maskHeight = maskWidth; maskWidth = temp; } //Height: screen height //Width: screen width //maskHeight: height of transparent area in the middle //maskWidth: width of transparent area in the middle int h = Math.abs((height - maskHeight) / 2);//Top shadow height int w = Math.abs((width - maskWidth) / 2);//Right shadow width //Upper shadow canvas.drawRect(0, 0, width, h, this.rectPaint); //Right shadow canvas.drawRect(width - w, h, width, height - h, this.rectPaint); //Lower shadow canvas.drawRect(0, height - h, width, height, this.rectPaint); //Left shadow canvas.drawRect(0, h, w, h + maskHeight, this.rectPaint); //Medium transparency canvas.drawRect(w, h, w + maskWidth, h + maskHeight, this.linePaint); canvas.save();//Save the top, bottom, left, right, middle //Medium top font canvas.rotate(90, width - w / 2, height/2);//Rotate the canvas 90 degrees canvas.drawText("Please scan the face of your ID witness", width - w / 2, height/2, topTextPaint); canvas.restore();//Restore the canvas to the last saved position to prevent this rotation from affecting the following operations //Middle bottom font canvas.rotate(90,w / 2, height/2);//Rotate 90 degrees canvas.drawText("Please keep the light sufficient, the background clean, and the mobile phone level with the card", w / 2, height/2, bottomTextPaint); //Print logo Log.e("Height width", "height:" + height + ",width:" + width + ",h:" + h + ",w:" + w + ",mskHeight:" + maskHeight + ",maskWidth:" + maskWidth); super.onDraw(canvas); } } }
Notes:
When using canvas canvas, pay attention to use save and restore. Because rotation is used to rotate the entire canvas, the layout behind will be affected. Therefore, before restoring the canvas to save, the new layout will not be affected.