自定义相机格线

最近在做自定义相机相关的内容,大概是给相机绘制九宫格这样一个功能。就在谷歌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<height*mRatioWidth/mRatioHeight)//哪边占比小就用它为绘制参考便,实际上是在选择同比例最大绘制范围
            {
                setMeasuredDimension(width,width*mRatioHeight/mRatioWidth);//设置SurfaceView的大小适应于预览流的大小
                specifiedWeight=width;//将当下绘制的SurfaceView的长宽比用于赋值,以便计算格线的位置
                specifiedHeight=width*mRatioHeight/mRatioWidth;
            }else{
                setMeasuredDimension(height*mRatioWidth/mRatioHeight,height);
                specifiedWeight=height*mRatioWidth/mRatioHeight;
                specifiedHeight=height;
            }
        }

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int x = specifiedWeight/(lineX + 1);
        int y = specifiedHeight/(lineY + 1);
        for(int i = 1 ; i <= lineX ; i++){
            canvas.drawLine(x * i, 0, x * i, height, mPaint);//绘制直线的起始(x,y)与终止(x1,y1)与画笔。
        }

        for (int i = 1; i <= lineY; i++) {
            canvas.drawLine(0, y * i, width, y * i, mPaint);
        }
    }


}

事实上在谷歌官方的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


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值