摄像头预览的背景带矩形框效果的实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
2013-01-29 14:34
741 查看
为了能在摄像头预览的时候,背景有个矩形框、或一些坐标、横线来标示关键位置,真让杂家费劲心思了。苦苦研究了两天,毫无进展。baidu了若干资料,大都是提出这个问题,但怎么解决的没有说,都不了了之。后来转而google,又研究了两天,终于完美解决啦!
1,网上介绍的摄像头预览,一般是用一个surfaceview,为了能让其正常预览视频,设置属性
mySurfaceView.setZOrderOnTop(true);
mySurfaceHolder = mySurfaceView.getHolder();
mySurfaceHolder.setFormat(PixelFormat.TRANSPARENT)
我先前也是在这种思路下,看能否加画个矩形框。这篇http://blog.sina.com.cn/s/blog_4e6922ab01010gfz.html文章提到一种方法,是用一个surfaceview,然后自己定义一个继承View的画矩形框的类DrawCaptureRect,经我实践,发现还是不中。用这种思路,在摄像头未预览的时候可以看到红色矩形框,但一点击预览,矩形框就被覆盖了。
2,还有一种思路是,在预览surfaceview的callback里面,取到canvas画布,然后画。这种思路也行不通,程序直接挂掉!
3,后来我想到了framelayout,用帧布局,融合第一种方法的思路,结果还是未能解决预览的时候,视频遮挡矩形框的问题。
4,还有人提出,给surfaceview或其所在的布局文件里加一个带矩形框的图片的方法,更是行不通!说这话的人真是站着不腰疼,别说背景设成带图片的矩形框,就是背景设成有颜色的,预览的surfaceview就不显示了,被遮挡了。
原来,当SurfaceHolder对象的类型设置为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS时就只能拍照不能绘制了,这就是为什么第二种思路程序会直接挂掉的原因。为了能够预览视频的同时绘制矩形框等信息,需要用两个同样大小的SurfaceView放在一个FrameLayout里,顶层的SurfaceView设成setZOrderOnTop(true); setFormat(PixelFormat.TRANSPARENT) ;预览的Surfaceview这两个属性就不用设置了。
首先在包yan.guoqi.testphoto下新建一个类SVDraw,如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201301/53fcc5151c823e2c15d3737cc06f05a2.jpg)
源码如下:
类里面的方法drawLine()就是画预览视频时背景矩形的,由于我需画一条线,上面程序就是画一条线和一个圆的。需要画什么图形,就在这里改!
注意在建这个类时构造函数里一定要有
public SVDraw(Context context, AttributeSet attrs) {
super(context, attrs);
AttributeSet attrs这个参数,否则是不能在xml文件里正常解析的。先前提到的http://blog.sina.com.cn/s/blog_4e6922ab01010gfz.html这位就没有引用这个参数,所以后来用了
addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)) 将这个对象加到布局中去!
上面的类建好之后,在布局文件里引用他,如下:
注意上面两个surfaceview是同样大小的,mySurfaceView是预览视频的,mDraw是用来画矩形的。
接下来就是在主Activity里引用这个mDraw。首先定义变量private SVDraw mSVDraw = null; 然后mSVDraw = (yan.guoqi.testphoto.SVDraw)findViewByIf(R.id.mDraw)。之后mSVDraw就可以用了,至于什么时候来画这个矩形,有人是在按下拍照按钮后,我选择的是在按下预览按钮后,
让其可见,然后调用drawLine()方法就可以了!你可以随时控制让其可见或者隐藏!
将上面这些代码融合我http://blog.csdn.net/yanzi1225627/article/details/7926994文章里http://download.csdn.net/detail/yanzi1225627/4538626这里的源码就可以了!即可以预览,自动聚焦,缩放标准大小,背景有矩形框!
来张图,有图有真相
![](https://oscdn.geek-share.com/Uploads/Images/Content/201301/de580ae0517701562a070d1512165361.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201301/926b1f1a0b670f07165e13bb1d0fc370.jpg)
反思:其实用第一种http://blog.sina.com.cn/s/blog_4e6922ab01010gfz.html这里的思路和本篇的思路合并起来,应该也是可行的,只不过一个是继承的view一个是surfaceview,将AttributeSet attrs加上。只要处理好谁是顶层的view谁设成透明,预览视频的surfaceview设成底层,在且要在xml属性文件里设成visible就可以了。有兴趣的自己试验吧。感谢大牛http://blog.csdn.net/xinzheng_wang/article/details/7712285对后生的指点!
-------------------作者yanzi1225627,转载请注明
1,网上介绍的摄像头预览,一般是用一个surfaceview,为了能让其正常预览视频,设置属性
mySurfaceView.setZOrderOnTop(true);
mySurfaceHolder = mySurfaceView.getHolder();
mySurfaceHolder.setFormat(PixelFormat.TRANSPARENT)
我先前也是在这种思路下,看能否加画个矩形框。这篇http://blog.sina.com.cn/s/blog_4e6922ab01010gfz.html文章提到一种方法,是用一个surfaceview,然后自己定义一个继承View的画矩形框的类DrawCaptureRect,经我实践,发现还是不中。用这种思路,在摄像头未预览的时候可以看到红色矩形框,但一点击预览,矩形框就被覆盖了。
2,还有一种思路是,在预览surfaceview的callback里面,取到canvas画布,然后画。这种思路也行不通,程序直接挂掉!
3,后来我想到了framelayout,用帧布局,融合第一种方法的思路,结果还是未能解决预览的时候,视频遮挡矩形框的问题。
4,还有人提出,给surfaceview或其所在的布局文件里加一个带矩形框的图片的方法,更是行不通!说这话的人真是站着不腰疼,别说背景设成带图片的矩形框,就是背景设成有颜色的,预览的surfaceview就不显示了,被遮挡了。
原来,当SurfaceHolder对象的类型设置为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS时就只能拍照不能绘制了,这就是为什么第二种思路程序会直接挂掉的原因。为了能够预览视频的同时绘制矩形框等信息,需要用两个同样大小的SurfaceView放在一个FrameLayout里,顶层的SurfaceView设成setZOrderOnTop(true); setFormat(PixelFormat.TRANSPARENT) ;预览的Surfaceview这两个属性就不用设置了。
首先在包yan.guoqi.testphoto下新建一个类SVDraw,如图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201301/53fcc5151c823e2c15d3737cc06f05a2.jpg)
源码如下:
package yan.guoqi.testphoto; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PixelFormat; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; /*定义一个画矩形框的类*/ public class SVDraw extends SurfaceView implements SurfaceHolder.Callback{ protected SurfaceHolder sh; private int mWidth; private int mHeight; public SVDraw(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub sh = getHolder(); sh.addCallback(this); sh.setFormat(PixelFormat.TRANSPARENT); setZOrderOnTop(true); } public void surfaceChanged(SurfaceHolder arg0, int arg1, int w, int h) { // TODO Auto-generated method stub mWidth = w; mHeight = h; } public void surfaceCreated(SurfaceHolder arg0) { // TODO Auto-generated method stub } public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub } void clearDraw() { Canvas canvas = sh.lockCanvas(); canvas.drawColor(Color.BLUE); sh.unlockCanvasAndPost(canvas); } public void drawLine() { Canvas canvas = sh.lockCanvas(); canvas.drawColor(Color.TRANSPARENT); Paint p = new Paint(); p.setAntiAlias(true); p.setColor(Color.RED); p.setStyle(Style.STROKE); //canvas.drawPoint(100.0f, 100.0f, p); canvas.drawLine(0,110, 500, 110, p); canvas.drawCircle(110, 110, 10.0f, p); sh.unlockCanvasAndPost(canvas); } }
类里面的方法drawLine()就是画预览视频时背景矩形的,由于我需画一条线,上面程序就是画一条线和一个圆的。需要画什么图形,就在这里改!
注意在建这个类时构造函数里一定要有
public SVDraw(Context context, AttributeSet attrs) {
super(context, attrs);
AttributeSet attrs这个参数,否则是不能在xml文件里正常解析的。先前提到的http://blog.sina.com.cn/s/blog_4e6922ab01010gfz.html这位就没有引用这个参数,所以后来用了
addContentView(mDraw, new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)) 将这个对象加到布局中去!
上面的类建好之后,在布局文件里引用他,如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:id="@+id/myFramelayout" android:layout_width="fill_parent" android:layout_height="800px" android:orientation="vertical" > <SurfaceView android:id="@+id/mySurfaceView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:visibility="visible" /> <yan.guoqi.testphoto.SVDraw android:id="@+id/mDraw" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </FrameLayout> <LinearLayout android:id="@+id/LinearLayout01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:orientation="horizontal" android:paddingTop="10dip" > <Button android:id="@+id/btnPreview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="预览" android:textSize="28sp" /> <Button android:id="@+id/btnPhoto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拍照" android:textSize="28sp" /> <Button android:id="@+id/btnSave" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="保存" android:textSize="28sp" /> </LinearLayout> </LinearLayout>
注意上面两个surfaceview是同样大小的,mySurfaceView是预览视频的,mDraw是用来画矩形的。
接下来就是在主Activity里引用这个mDraw。首先定义变量private SVDraw mSVDraw = null; 然后mSVDraw = (yan.guoqi.testphoto.SVDraw)findViewByIf(R.id.mDraw)。之后mSVDraw就可以用了,至于什么时候来画这个矩形,有人是在按下拍照按钮后,我选择的是在按下预览按钮后,
case R.id.btnPreview: Toast.makeText(TestPhotoActivity.this, "您按了预览按钮", Toast.LENGTH_SHORT).show(); initCamera(); mDraw.setVisibility(View.VISIBLE); mDraw.drawLine(); break;
让其可见,然后调用drawLine()方法就可以了!你可以随时控制让其可见或者隐藏!
将上面这些代码融合我http://blog.csdn.net/yanzi1225627/article/details/7926994文章里http://download.csdn.net/detail/yanzi1225627/4538626这里的源码就可以了!即可以预览,自动聚焦,缩放标准大小,背景有矩形框!
来张图,有图有真相
![](https://oscdn.geek-share.com/Uploads/Images/Content/201301/de580ae0517701562a070d1512165361.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201301/926b1f1a0b670f07165e13bb1d0fc370.jpg)
反思:其实用第一种http://blog.sina.com.cn/s/blog_4e6922ab01010gfz.html这里的思路和本篇的思路合并起来,应该也是可行的,只不过一个是继承的view一个是surfaceview,将AttributeSet attrs加上。只要处理好谁是顶层的view谁设成透明,预览视频的surfaceview设成底层,在且要在xml属性文件里设成visible就可以了。有兴趣的自己试验吧。感谢大牛http://blog.csdn.net/xinzheng_wang/article/details/7712285对后生的指点!
-------------------作者yanzi1225627,转载请注明
相关文章推荐
- Android开发 摄像头SurfaceView预览 背景带矩形框 实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- 只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
- Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)
- Android开发:巧用延迟实现欢迎界面 及 摄像头预览后绘制背景标示(如坐标系、矩形框)
- 使用SurfaceView和MediaPlayer实现视频做为背景
- 通过Camera、SurfaceView、自己实现拍照及预览效果
- camera2 opengl实现滤镜效果录制视频 二 双SurfaceView渲染
- 使用SurfaceView和MediaPlayer实现视频做为背景
- 自定义View很简单 - Android翻页效果原理实现之翻页的尝试
- 使用surfaceView实现视频播放
- react native 实现surfaceview播放视频
- 安卓飞机大战(二) SurfaceView实现自制背景
- SurfaceView实现视频播放
- Android踩坑日记:点击变暗效果的ImageView实现原理
- Android - SurfaceView + MediaPlayer实现分段视频无缝播放
- Android MediaPlayer+SurfaceView实现视频播放
- VideoView 实现引导页播放视频欢迎效果