自定义相机格线

最近在做自定义相机相关的内容,大概是给相机绘制九宫格这样一个功能。就在谷歌Camera2API demo的基础上略作修改,权当一个记录。

效果如下:


主要就是在TextureView这个显示相机预览的视图上覆盖一个自定义的SurfaceView,在SurfaceView上面绘制九宫格。曾经尝试过直接在TextureView上画九宫格但是失败了,因为TextureView根本没有onDraw方法。

以下是自定义SurfaceView的内容

package com.example.android.camera2basic;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceView;

/**
 * Created by txs on 2018/5/25.
 */

public class MySurfaceView extends SurfaceView {
    private int lineX=2;
    private int lineY=2;
    private Paint mPaint=null;
    private int width;
    private int height;
    private  int mRatioWidth=0;
    private int mRatioHeight=0;
    private int specifiedWeight;
    private int specifiedHeight;

    public MySurfaceView(Context context) {
        this(context,null);
    }

    public MySurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MySurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.GridAutoTextureView);
        lineX=a.getInteger(R.styleable.GridAutoTextureView_linesX,lineX);
        lineY=a.getInteger(R.styleable.GridAutoTextureView_linesY,lineY);
        a.recycle();
        init();
        setWillNotDraw(false);//这个方法是保证回调ondraw方法用的,可以考虑用监听Surface状态的时候使用
    }

    /**
     * 设置长宽比
     */
    public void setAspectRatio(int width,int heigth){
        if(width<0||heigth<0){
            throw new IllegalArgumentException("长宽参数不能为负");
        }
        mRatioHeight=heigth;
        mRatioWidth=width;
        requestLayout();//宽高比之后重新绘制
    }

    private void init() {//关于paint类
        mPaint=new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置画笔的类型是填充,还是描边,还是描边且填充
        mPaint.setStrokeWidth(1);//设置笔刷的粗细
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         width= MeasureSpec.getSize(widthMeasureSpec);
         height= MeasureSpec.getSize(heightMeasureSpec);
        if(0==mRatioWidth||0==mRatioHeight){//初次绘制的情况
            setMeasuredDimension(width,height);
            specifiedWeight=width;//将当下绘制的SurfaceView的长宽比用于赋值,以便计算格线的位置
            specifiedHeight=height;
        }else{
            if(width

事实上在谷歌官方的demo中做了一个可以自适应相机宽高比的TextureView,来解决相机预览时候的拉伸问题,为了和TextureView保持同步的大小,所以在SurfaceView里我采用了和AutoFitTextureView一样的绘制方案。在相机选择好预览比例后会直接给TextureView和SurfaceView的setAspectRatio方法赋值。以保证在测量和绘制上的同步性。

在这里遇到两个问题需要注意下:

1.就是SurfaceView默认不回调onDraw方法,在初始化的时候我加了一行代码让它回调onDraw方法

2.另一点就是SurfaceView与TextureView的叠图问题,虽然我在代码里设置了SurfaceView让它在上层视图,但是如果我在XML文件中如果还是让SurfaceView在TextureView之上,还是会被TextureView覆盖。

AutoFitTextureView的示例代码如下:

/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.camera2basic;

import android.content.Context;
import android.util.AttributeSet;
import android.view.TextureView;

/**
 * A {@link TextureView} that can be adjusted to a specified aspect ratio.
 */
public class AutoFitTextureView extends TextureView {

    private int mRatioWidth = 0;
    private int mRatioHeight = 0;

    public AutoFitTextureView(Context context) {
        this(context, null);
    }

    public AutoFitTextureView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
     * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
     * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
     *
     * @param width  Relative horizontal size
     * @param height Relative vertical size
     */
    public void setAspectRatio(int width, int height) {
        if (width < 0 || height < 0) {
            throw new IllegalArgumentException("Size cannot be negative.");
        }
        mRatioWidth = width;
        mRatioHeight = height;
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (0 == mRatioWidth || 0 == mRatioHeight) {
            setMeasuredDimension(width, height);
        } else {
            if (width < height * mRatioWidth / mRatioHeight) {
                setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
            } else {
                setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
            }
        }
    }

}

下载链接如下:https://github.com/a1850524995/android-Camera2Basic-master


你可能感兴趣的:(Android学习)