Android Studio:使用Camera拍照(三)为相机增加取景蒙板/浮层

写在前面的话:每一个实例的代码都会附上相应的代码片或者图片,保证代码完整展示在博客中。最重要的是保证例程的完整性!!!方便自己也方便他人~欢迎大家交流讨论~本文为博主原创文章,未经博主允许不得转载。

在相机预览时增加取景蒙板/浮层的思路是自定义View,用framelayout把自定义view放在surfaceview上面,在oncreat方法中计算坐标位置,调用自定义view中的set…方法设置坐标,根据坐标绘图。
接下来把上篇的自定义相机和增加蒙板那篇的代码结合起来,为相机增加取景蒙板/浮层,上代码!

新建一个Android项目

取名为Cameratwo,具体文件的命名如下
这里写图片描述

values文件夹

strings.xml

<resources>
    <string name="app_name">Cameratwo</string>
    <string name="button_name">开始拍照</string>
</resources>

layout文件夹

activity_first.xml

<?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:orientation="vertical"
    tools:context=".FirstActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="customCamera"
        android:text="@string/button_name" />

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

custom.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true">

        <SurfaceView
            android:id="@+id/preview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="visible" />

        <com.example.administrator.cameratwo.TranslucencyView
            android:id="@+id/transView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

    <ImageButton
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:background="@drawable/button3"
        android:onClick="capture" />
</RelativeLayout>

result.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/pic"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

manifests

AndroidManifest.xml

在该文件中增加以下两项

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.Camera"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<activity android:name=".Customcamera"/>
<activity android:name=".ResultActivity"/>

Java文件夹

FirstActivity

package com.example.administrator.cameratwo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;

public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
    }
    public void  customCamera(View view){
        startActivity(new Intent(this,Customcamera.class));
    }
}

Customcamera

这里完全没有用到Butter Knife 框架,因为我用的不熟,就删掉了orz…

package com.example.administrator.cameratwo;

import android.content.Intent;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Customcamera extends AppCompatActivity implements SurfaceHolder.Callback{
    private Camera mCamera;
    private SurfaceView mPreview;
    private SurfaceHolder mHolder;
    private int cameraId=1;
    private int mHeight;

    private Camera.PictureCallback mpictureCallback=new Camera.PictureCallback(){
        @Override
        public void onPictureTaken(byte[] data,Camera camera){
            File tempfile=new File("/sdcard/emp.png");
            try{ FileOutputStream fos =new FileOutputStream(tempfile);
                fos.write(data);
                fos.close();
                Intent intent=new Intent(Customcamera.this,ResultActivity.class);
                intent.putExtra("picpath",tempfile.getAbsolutePath());
                startActivity(intent);
                Customcamera.this.finish();
            }
            catch (IOException e){e.printStackTrace();}
        }
    };
    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom);
        mPreview=findViewById(R.id.preview);
        mPreview.setZOrderOnTop(false);
        mHolder=mPreview.getHolder();
        mHolder.setFormat(PixelFormat.TRANSPARENT);
        mHolder.addCallback(this);
        mPreview.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCamera.autoFocus(null);
            }
        });
       //获取imgButton的坐标,以便蒙板在imgButton处掏空,并获取页面参数
        ImageButton imgButton=findViewById(R.id.button3);
        TranslucencyView translucencyView=findViewById(R.id.transView);
        imgButton.postDelayed(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        ImageButton imgButton=findViewById(R.id.button3);
                        mHeight = getSupportActionBar().getHeight();
                        int left = imgButton.getLeft();
                        int right = imgButton.getRight();
                        int top = imgButton.getTop();
                        int bottom = imgButton.getBottom();
                        int mCoodinate[] = {left, top, right, bottom};
                        TranslucencyView translucencyView=findViewById(R.id.transView);
                        translucencyView.setCircleLocation(mCoodinate);
                    }
                });
            }
        },1200);
        FrameLayout.LayoutParams layoutParams=(FrameLayout.LayoutParams) translucencyView.getLayoutParams();
        translucencyView.setLayoutParams(layoutParams);
        translucencyView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mCamera.autoFocus(null);
                return false;
            }
        });
        mHolder.lockCanvas();
    }

    public void capture(View view){
        Camera.Parameters parameters=mCamera.getParameters();
        parameters.setPictureFormat(ImageFormat.JPEG);
        parameters.setPreviewSize(800,400);
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        mCamera.autoFocus(new Camera.AutoFocusCallback(){
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                if(success){mCamera.takePicture(null,null, mpictureCallback);}
            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mCamera==null){
            mCamera=getCamera();
            if(mHolder!=null){
                setStartPreview(mCamera,mHolder);}
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera(); }

        private Camera getCamera(){
        Camera camera;
        try{
            camera=Camera.open(cameraId);
            }
        catch (Exception e){
            camera=null;
            e.printStackTrace(); }
        return camera;
    }

    private void setStartPreview(Camera camera,SurfaceHolder holder){
        try{
            camera.setPreviewDisplay(holder);
            camera.setDisplayOrientation(90);
            camera.startPreview();
        }
        catch (Exception e){
            e.printStackTrace(); }
    }
    private void releaseCamera(){
        if(mCamera!=null){
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera=null;
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        setStartPreview(mCamera,mHolder);
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mCamera.stopPreview();
        setStartPreview(mCamera,mHolder);
        }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
    }

   @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus); }

}

TranslucencyView

package com.example.administrator.cameratwo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;

public class TranslucencyView extends  ImageView{
    private  final Context mContext;
    private int[] mCircleLocation;//声明存放坐标的数组

    public TranslucencyView(Context context){this(context,null);}
    public TranslucencyView(Context context, AttributeSet attributeSet){this(context,attributeSet,0);}
    public TranslucencyView(Context context,AttributeSet attributeSet,int defStyleAttr){
        super(context,attributeSet,defStyleAttr);
        this.mContext=context;
        initView();
    }

    private void initView(){setBackgroundColor(Color.parseColor("#7f000000"));}//设置半透明底色
    public void setCircleLocation(int[] location){
        this.mCircleLocation=location;
        invalidate();
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(mCircleLocation!=null){
            //掏空一个圆形
            Paint paintarc=new Paint(Paint.ANTI_ALIAS_FLAG);//创建一个画笔实例
            PorterDuffXfermode porterDuffXfermode=new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
            paintarc.setXfermode(porterDuffXfermode);
            paintarc.setAntiAlias(true);
            RectF rectF=new RectF(mCircleLocation[0],mCircleLocation[1],mCircleLocation[2],mCircleLocation[3]);
            canvas.drawArc(rectF,0,360,true,paintarc);
            //画虚线
            Paint paintdashed=new Paint(Paint.ANTI_ALIAS_FLAG);
            paintdashed.setStyle(Paint.Style.STROKE);
            paintdashed.setColor(Color.WHITE);
            paintdashed.setStrokeWidth(5);
            PathEffect pathEffect=new DashPathEffect(new float[]{10,10},0);
            paintdashed.setPathEffect(pathEffect);
            canvas.drawArc(rectF,0,360,true,paintdashed);
            //画矩形框
           /** Paint paintrect=new Paint(Paint.ANTI_ALIAS_FLAG);
            PorterDuffXfermode porterDuffXfermode1=new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
            paintrect.setXfermode(porterDuffXfermode1);
            paintrect.setAntiAlias(true);
            //paintrect.setStrokeWidth(5);
            canvas.drawRect(200, 400, 900, 1300, paintrect);*/
            //画椭圆
            Paint paintoval=new Paint(Paint.ANTI_ALIAS_FLAG);
            PorterDuffXfermode porterDuffXfermode2=new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
            paintoval.setXfermode(porterDuffXfermode2);
            paintoval.setAntiAlias(true);
            //paintoval.setStrokeWidth(10);
            canvas.drawOval(100,200,1000,1200,paintoval);
              }
    }
}         

这里画了个椭圆,注意用的都是绝对坐标,我估计在不同的手机中可能会出现适配问题,不过还没想好相对的怎么画啦

ResultActivity

这个的代码和之前的3.3ResultActivity.java代码一模一样,大家直接看
Android Studio:使用Camera拍照(二)自定义相机 - CSDN博客 https://blog.csdn.net/Leo_Huang720/article/details/81289309#33resultactivityjava就可以了

小结

上完了代码,我要小结一下给相机加取景蒙版和之前一篇的直接添加(文章后面有附上)有什么差别,我最开始的时候确实是很简单的两处代码合在一起,然后执行时发现两个问题:
1.整个显示出来的是深蓝色的
2.在蒙版还没稳定出现前,surfaceview尚在预览,蒙板稳定出现后,surfaceview瞬间卡在了那时的页面
解决问题1:我又回去看了自定义相机的执行(那个项目叫startcamera),发现surfaceview从开始到预览确实有个从暗变深蓝再变浅的过程,于是我猜是 showMask() 方法(这个方法中的内容后来被单独拿出来放到了onCreate中)中设置的时间太短,该时间用于测量view是够了(因为蒙板能顺利显示,如果时间不够,整个页面其实会闪退),那就是通过intent传给TranslucencyActivity.java的时间太短,surfaceview还没构造完,intent就把坐标信息给TranslucencyActivity了,于是我把时间从500ms改到1200ms
解决问题2:其实从解决问题1的最后几句话已经能看出问题2的端倪了,就是原本的showMask() 最后有几句代码:

Intent intent = new Intent(SecondActivity.this, TranslucencyActivity.class);
intent.putExtra("Location", mCoodinate);
startActivity(intent);

这就意味着信使不仅将坐标传给TranslucencyActivity,还打开了TranslucencyActivity!!那这个界面就把surfaceview定住了,因为TranslucencyActivity没有任何写预览的方法,它只是把自定义的view和自己的页面绑在一起,所以要弄取景框蒙板没有TranslucencyActivity任何事情,我就把它删掉了,其他所做的更改上面代码已详细给出。

执行效果:
这里写图片描述
附: Android Studio:增加蒙板/浮层特效 - CSDN博客 https://blog.csdn.net/Leo_Huang720/article/details/81542015#secondactivityjava
Android Studio:使用Camera拍照(二)自定义相机 - CSDN博客https://blog.csdn.net/Leo_Huang720/article/details/81289309#33resultactivityjava

猜你喜欢

转载自blog.csdn.net/Leo_Huang720/article/details/81587035
今日推荐