Android - Paint自定义外部阴影,内部透明画布蒙版布局

说明:

一个简单的需求,外部阴影,内部是透明布局的,最底层打开相机(这里只有布局的代码,带相机点击这里)。

代码:

1、调用 

直接在Activity中调用就行了,设置中间区域的高度和宽度

Activity代码

private OcrFaceMaskSurfaceView surfaceview;
surfaceview = (OcrFaceMaskSurfaceView) findViewById(R.id.surface_view);
surfaceview.setMaskSize(900, 600);

Activity布局

<?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 就是自定义的画布

实现思路:

(1)自定义布局中两层画布,第一层画布只是启动和加载相机

(2)第二层画布画出外部阴影和内部透明,再加上里面的文字

代码如下:(里面的CameraHelper这个是相机工具类,可注释掉,点击这里看到带相机的完整代码+demo

(3)UiUtil工具类 - 点击这里

(4)代码注释里面很清楚

package com.gxjl.pe.gxjlpesdk.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
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.R;
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;//加载相机的蒙版
    private MaskView maskView;//加载布局的蒙版
    private int width;//屏幕宽度
    private int height;//屏幕高度
    private int maskWidth;//中部透明区域宽度
    private int maskHeight;//中部透明区域高度
    private int screenWidth;//相机拍照截取宽度
    private int screenHeight;//相机拍照截取高度

    public OcrFaceMaskSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);

        this.context = context;

        surfaceView = new MSurfaceView(context);//第一层画布用来加载相机
        maskView = new MaskView(context);//第二层画布用来画所有布局
        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[]{maskWidth, maskHeight, width, height};
        }
    }

    /**
     * 承载相机的布局
     */
    private class MSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder holder;

        public MSurfaceView(Context context) {
            super(context);
            this.holder = this.getHolder();
            //translucent半透明 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();
        }
    }

    /**
     * 蒙层所有布局
     */
    private class MaskView extends View {
        private Paint linePaint;
        private Paint rectPaint;
        private Paint topTextPaint;
        private Paint bottomTextPaint;

        public MaskView(Context context) {
            super(context);

            //绘制中间透明区域矩形边界的Paint
            linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            linePaint.setColor(Color.TRANSPARENT);//设置中间区域颜色为透明
            linePaint.setStyle(Style.STROKE);
            linePaint.setStrokeWidth(3f);
            linePaint.setAlpha(0);//取值范围为0~255,数值越小越透明

            //绘制四周矩形阴影区域
            rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            rectPaint.setColor(Color.BLACK);
            rectPaint.setStyle(Style.FILL);
            rectPaint.setAlpha(170);//取值范围为0~255,数值越小越透明

            //绘制顶部中间提示字体
            topTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            topTextPaint.setColor(Color.WHITE);
            //topTextPaint.setStyle(Paint.Style.FILL);
            topTextPaint.setTextAlign(Paint.Align.CENTER);//把x,y坐标放到字体中间(默认x,y坐标是字体头部)
            topTextPaint.setTextSize(UiUtil.sp2px(context, 14));

            //绘制顶部中间提示字体
            bottomTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            bottomTextPaint.setColor(Color.parseColor("#A0A0A0"));
            //bottomTextPaint.setStyle(Paint.Style.FILL);
            bottomTextPaint.setTextAlign(Paint.Align.CENTER);//把x,y坐标放到字体中间(默认x,y坐标是字体头部)
            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:屏幕高度
            //width:屏幕宽度
            //maskHeight:中间透明区域高度
            //maskWidth:中间透明区域宽度
            int h = Math.abs((height - maskHeight) / 2);//顶部阴影高度
            int w = Math.abs((width - maskWidth) / 2);//右侧阴影宽度

            //上阴影
            canvas.drawRect(0, 0, width, h, this.rectPaint);
            //右阴影
            canvas.drawRect(width - w, h, width, height - h, this.rectPaint);
            //下阴影
            canvas.drawRect(0, height - h, width, height, this.rectPaint);
            //左阴影
            canvas.drawRect(0, h, w, h + maskHeight, this.rectPaint);
            //中透明
            canvas.drawRect(w, h, w + maskWidth, h + maskHeight, this.linePaint);
            canvas.save();//保存上面的上下左右中
            //中-顶部-字体
            canvas.rotate(90, width - w / 2, height / 2);//把画布旋转旋转90度
            canvas.drawText("请扫描本人身份证人像面", width - w / 2, height / 2, topTextPaint);
            canvas.restore();//把画布恢复到上次保存的位置,防止本次旋转影响下面的操作
            canvas.save();//保存中顶部字体
            //中-底部-字体
            canvas.rotate(90, w / 2, height / 2);//旋转90度
            canvas.drawText("请保持光线充足,背景干净,手机与卡片持平", w / 2, height / 2, bottomTextPaint);
            canvas.restore();//把画布恢复到上次保存的位置,防止本次旋转影响下面的操作
            canvas.save();//保存中底部字体
            //身份证头像框 - 画图片,就是贴图
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_face_border);
            canvas.rotate(90, width - w  - 80, height - h - bitmap.getHeight() - 30);//把画布旋转旋转90度
            canvas.drawBitmap(bitmap, width - w  - 80, height - h - bitmap.getHeight() - 30, new Paint());

            //打印logo
            Log.e("高度宽度", "height:" + height + ",width:" + width + ",h:" + h + ",w:" + w + ",mskHeight:" + maskHeight + ",maskWidth:" + maskWidth);

            super.onDraw(canvas);
        }
    }
}

注解:

画布canvas使用的时候注意使用save和restore,因为自已旋转使用rotate把整个画布给旋转了,导致后面的布局有影响,所以把画布restore恢复到save之前,那么新的布局就不会受到影响了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Beluga_白鲸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值