最近在做自定义相机相关的内容,大概是给相机绘制九宫格这样一个功能。就在谷歌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