我是靠谱客的博主 故意芝麻,最近开发中收集的这篇文章主要介绍SurfaceView 简单使用,解决背景透明,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 

目录

SurfaceView 和View 的比较大的区别

双缓冲机制

SurfaceView 的简单使用

使用SurfaceView背景问题


网上的文章很齐全了,我根据看的文章写(粘贴)了一点小小的总结,当然,英语比较好的直接看官网的描述是最好的了。

SurfaceView 和View 的比较大的区别

1.View的绘图效率不高,主要用于动画变化较少的程序,SurfaceView 绘图效率较高,我们播放视频,绘制变化较大的动画,都可以使用SurfaceView。

2.View的刷新是要在主线程进行的,而主线程还承担着界面响应的任务,SurfaceView 则可以在子线程中进行刷新操作。

3.SurfaceView拥有独立的Surface,即它不与其宿主窗口共享同一个Surface。一般来说,每一个窗口在SurfaceFlinger服务中都对应有一个Layer,用来描述它的绘图表面。对于那些具有SurfaceView的窗口来说,每一个SurfaceView在SurfaceFlinger服务中还对应有一个独立的Layer或者LayerBuffer,用来单独描述它的绘图表面,以区别于它的宿主窗口的绘图表面。

(https://www.jianshu.com/p/56da8a2f377a)想要了解的朋友可以仔细阅读以下这系列的文章

4.SurfaceView使用双缓冲机制,播放视频时画面更流畅。

双缓冲机制

在运用时可以理解为:SurfaceView在更新视图时用到了两张 Canvas,一张 frontCanvas 和一张 backCanvas ,每次实际显示的是 frontCanvas ,backCanvas 存储的是上一次更改前的视图。当你在播放这一帧的时候,它已经提前帮你加载好后面一帧了,所以播放起视频很流畅。
当使用lockCanvas()获取画布时,得到的实际上是backCanvas 而不是正在显示的 frontCanvas ,之后你在获取到的 backCanvas 上绘制新视图,再 unlockCanvasAndPost(canvas)此视图,那么上传的这张 canvas 将替换原来的 frontCanvas 作为新的frontCanvas ,原来的 frontCanvas 将切换到后台作为 backCanvas 。例如,如果你已经先后两次绘制了视图A和B,那么你再调用 lockCanvas()获取视图,获得的将是A而不是正在显示的B,之后你将重绘的 A 视图上传,那么 A 将取代 B 作为新的 frontCanvas 显示在SurfaceView 上,原来的B则转换为backCanvas。相当与多个线程,交替解析和渲染每一帧视频数据。

SurfaceView 的简单使用

创建MySurfaceView 继承 SurfaceView 实现 SurfaceHolder.Callback 回调 ,以及最好实现 Runnable 接口

public class MySufaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
public MySufaceView(Context context) {
super(context);
}
public MySufaceView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MySufaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void run() {
}
}

初始化Holder

创建init() 方法,在构造函数里面调用该方法来注册回调。


public void init(){
mSurfaceHolder = this.getHolder();
// 注册回调方法
mSurfaceHolder.addCallback(this);
//设置背景透明
getHolder().setFormat(PixelFormat.TRANSLUCENT);
}

如果要在SurfaceView 中进行耗时操作,最好在surfaceCreated() 方法中创建一个新的线程 指定为当前。


@Override
public void surfaceCreated(SurfaceHolder holder)
{
LogUtils.i(TAG,"surfaceCreated : view创建");
// 创建surfaceView时启动线程,如果有使用到线程池,也可以用线程池的线程
new Thread(this).start();
}

新线程中的操作

在run()方法中,我们可以进行自己的绘制工作了。


//isRun 标记位
while (isRun)
{
synchronized (this) {
// 锁定画布
mCanvas = mSurfaceHolder.lockCanvas();
try {
if (mSurfaceHolder != null && mCanvas != null) {
//......dosomething
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//绘制结束后
// 将画布解锁
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}

使用SurfaceView背景问题

1.如果希望你的surfaceview 在最顶端,并且会遮挡一切view 

   setZOrderOnTop(true) ;

2.如果你希望在最顶端,并且让背景透明化,那么只要加上以下代码,即可设置为顶端且透明。

  setZOrderOnTop(true) ;

getHolder().setFormat(PixelFormat.TRANSPARENT);

3.如果你希望你的surfaceview 仅仅是让他的背景透明,但是却不透底,(所谓的透底则是因为主题设置了windowIsTranslucent的缘故,直接挖空了布局显示了最底层的手机桌面。)使用以下方式即可:

  getHolder().setFormat(PixelFormat.TRANSPARENT);//初始化的时候调用。

然后在surfaceCreated 方法中,添加自己想要的背景。

mCanvas = mSurfaceHolder.lockCanvas();
if (mCanvas!=null){
mCanvas.drawColor(getResources().getColor(设置自己想设置的颜色));
}
mSurfaceHolder.unlockCanvasAndPost(mCanvas); 

这里需要注意,如果你调用了mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

那么每次都会清除掉背景,你必须重新调用绘制背景的代码。

 

4.如果在surfaceView上绘制surfaceView ,最好使用外层布局包裹surfaceview 的方式。必须在layout.addView之后使用,必须动态调用。

  layout.addView(surfaceView);
  surfaceView.setZOrderMediaOverlay(true);  
 

 

最后:我是看了如下作者的文章:

这两位也是简单讲述了一下 

https://www.jianshu.com/p/a2a235bee59e 

https://www.jianshu.com/p/90a75b9b7115  

这里写了suface 的创建过程

https://www.jianshu.com/p/56da8a2f377a   

 

最后

以上就是故意芝麻为你收集整理的SurfaceView 简单使用,解决背景透明的全部内容,希望文章能够帮你解决SurfaceView 简单使用,解决背景透明所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部