相机遮罩实现原理,FrameLayout中如果控件一样大,同一时间只能见到最上面的。

1.自定义ViewFindView,相机遮罩界面

public class ViewFinderView extends View {    //相机遮罩框外面的线,阴影区域,滚动线    private Paint border, area, line;    //相机遮罩框中间透明区域    private Rect center;    //屏幕大小    private int screenHeight, screenWidth;    //滚动线的起始点    private int startX, startY, endX, endY;    //滚动线向下滚动标识    private boolean isDown = true;    //滚动线速度    private static final int SPEED = 2;    //中间区域宽高(dp),    public static final int centerHeight = 300;    public static final int centerWidth = 300;    public ViewFinder(Context context) {        super(context);    }    public ViewFinder(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        //setAlpha一定要在setStyle后面,否则不起作用        border = new Paint(Paint.ANTI_ALIAS_FLAG);        border.setColor(Color.BLUE);        border.setStyle(Paint.Style.STROKE);        border.setStrokeWidth(5f);        border.setAlpha(10);        area = new Paint(Paint.ANTI_ALIAS_FLAG);        area.setStyle(Paint.Style.FILL);        area.setColor(Color.GRAY);        area.setAlpha(180);        screenHeight = DimenUtil.getScreenSize(context).heightPixels;        screenWidth = DimenUtil.getScreenSize(context).widthPixels;        center = getCenterRect(context, 300, 300);        line = new Paint(Paint.ANTI_ALIAS_FLAG);        line.setStyle(Paint.Style.STROKE);        line.setColor(Color.GREEN);        //设置滚动线的起始点        startX = center.left;        startY = center.top;        endX = center.right;        endY = center.top;    }    public ViewFinder(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    /**     * 根据尺寸获取中间区大小     *     * @param context     * @param height     * @param width     * @return     */    private Rect getCenterRect(Context context, int height, int width) {        height = DimenUtil.px2dip(context, height);        width = DimenUtil.px2dip(context, width);        Rect rect = new Rect();        int left = (this.screenWidth - width) / 2;        int top = (this.screenHeight - height) / 2;        rect.set(left, top, left + width, top + height);        return rect;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //绘制四周阴影区域(上下左右),注意+1和-1,不设置不显示边框        canvas.drawRect(0, 0, screenWidth, center.top - 1, area);        canvas.drawRect(0, center.bottom + 1, screenWidth, screenHeight, area);        canvas.drawRect(0, center.top - 1, center.left - 1, center.bottom + 1, area);        canvas.drawRect(center.right + 1, center.top - 1, screenWidth, center.bottom + 1, area);        canvas.drawRect(center, border);        //滚动线        if (isDown) {            startY = endY += SPEED;            if (startY >= center.bottom)                isDown = false;        } else {            startY = endY -= SPEED;            if (startY <= center.top)                isDown = true;        }        canvas.drawLine(startX, startY, endX, endY, line);        postInvalidate();    }}

2.DimenUtil

public class DimenUtil {    //dp转px    public static int dip2px(Context context, int dp) {        float density = context.getResources().getDisplayMetrics().density;        return (int) (dp * density + 0.5f);    }    //px转dp    public static int px2dip(Context context, int px) {        float density = context.getResources().getDisplayMetrics().density;        return (int) (px / density + 0.5f);    }    //获取屏幕大小(px)    public static DisplayMetrics getScreenSize(Context context) {        return context.getResources().getDisplayMetrics();    }}

3.主界面 MainActivity

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback2, Camera.AutoFocusCallback, Camera.PreviewCallback, SensorEventListener {    private Camera camera;    private SurfaceHolder holder;    private SurfaceView surfaceView;    //传感器    private SensorManager manager;    //上次加速时间戳    private long lastTime;    //聚焦标识    private static boolean isFocusing;    //Android重力加速度传感器数据去噪    private float[] grivity = new float[3];    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        surfaceView = findViewById(R.id.surfaceview);        //相机个数        int count = Camera.getNumberOfCameras();        //默认设置后置摄像头        if (count <= 0) {            Toast.makeText(this, "您的手机不支持相机", Toast.LENGTH_SHORT).show();            return;        } else if (count == 1) {            camera = Camera.open();        } else {            camera = Camera.open(0);        }        //设置旋转90度        camera.setDisplayOrientation(90);        Camera.Parameters parameters = camera.getParameters();        //设置自动聚焦模式        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);        camera.setParameters(parameters);        camera.setPreviewCallback(this);        camera.autoFocus(this);        holder = surfaceView.getHolder();        holder.addCallback(this);        manager = (SensorManager) getSystemService(SENSOR_SERVICE);    }    @Override    public void surfaceRedrawNeeded(SurfaceHolder surfaceHolder) {    }    @Override    public void surfaceCreated(SurfaceHolder surfaceHolder) {        if (surfaceHolder.getSurface() == null)            return;        try {            camera.setPreviewDisplay(holder);            camera.startPreview();            //注册传感器            manager.registerListener(this, manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);        } catch (IOException e) {            e.printStackTrace();        }    }    @Override    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {    }    @Override    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {        //取消传感器        manager.unregisterListener(this);        camera.stopPreview();        //这个必须加,否则报错Camera is being used after Camera.release() was called        camera.setPreviewCallback(null);        camera.release();        camera = null;    }    @Override    public void onAutoFocus(boolean b, Camera camera) {        if (b) {            isFocusing = false;            //连续聚焦必须加这段,每次聚焦成功之后取消自动聚焦            camera.cancelAutoFocus();            Toast.makeText(this, "聚焦成功", Toast.LENGTH_SHORT).show();        }    }    @Override    public void onPreviewFrame(byte[] bytes, Camera camera) {        //此处用byte生成YuvImage,然后旋转90度,按照ViewFinderView中的centerHeight和centerWidth计算出中间框        //的位置,裁剪之后处理中间图片的数据(二维码,图片....)    }    @Override    public void onSensorChanged(SensorEvent sensorEvent) {        switch (sensorEvent.sensor.getType()) {            case Sensor.TYPE_ACCELEROMETER:                final float alpha = 0.8f;//为啥0.8我也不知道                grivity[0] = alpha * grivity[0] + (1 - alpha) * sensorEvent.values[0];                grivity[1] = alpha * grivity[1] + (1 - alpha) * sensorEvent.values[1];                grivity[2] = alpha * grivity[2] + (1 - alpha) * sensorEvent.values[2];                //取绝对值                float x = Math.abs(sensorEvent.values[0] - grivity[0]);                float y = Math.abs(sensorEvent.values[1] - grivity[1]);                float z = Math.abs(sensorEvent.values[2] - grivity[2]);                //获取当前时间戳                long current = System.currentTimeMillis();                if ((x + y + z) / 3 < 0.3 && !isFocusing && current - lastTime > 500 && current - lastTime < 1500) {                    //相对静止并且不在聚焦,加速完成后500-1500ms之间进行聚焦                    isFocusing = true;                    camera.autoFocus(this);                } else if ((x + y + z) / 3 > 0.3) {                    //相对正在加速                    isFocusing = false;                    lastTime = current;                }                break;        }    }    @Override    public void onAccuracyChanged(Sensor sensor, int i) {        //精度发生改变调用    }}

4.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>                        

注释写的挺详细的了,功能基本实现

福利

大牛的CSDN,参考他的也行

更多相关文章

  1. 数据更新后让ListView自动滚动到底部
  2. android实现垂直方向跑马灯效果
  3. Android(安卓)使用OPENCV实现图像实时对比
  4. Android(安卓)调用相机拍照并显示,打开相册并显示
  5. android相机Camera.Parameters所有的参数值
  6. Android(安卓)源码 listview 重用机制 浅析
  7. 自定义View详解
  8. android DIY 2
  9. Android中使用系统相机进行拍照并获取高清照片(一)

随机推荐

  1. Android下修改SeekBar样式
  2. Android(安卓)动态获取资源ID
  3. Android(安卓)Activity传递自定义对象
  4. android音乐播放器
  5. Android(安卓)坐标
  6. android 加载第三方库
  7. android保存预览图片
  8. android调用系统添加联系人界面
  9. Android通过画线实现button效果
  10. android 实现透明按钮