zoukankan      html  css  js  c++  java
  • surface知识点

    SurfaceView和TextureView

    在学习直播的过程遇到一个问题:连麦场景下能够支持大小窗口切换(即小窗口变大,大窗口变小),大窗口是TextView(用于拉流显示),而小窗口是SurfaceView(用于推流时的本地预览),切换的思路是直接改变View大小,在将TextView变小后还能正常显示,但是将SurfaceView的变大后直接黑屏。所以需要研究一下SurfaceView和TextureView的区别。

    帧缓冲区(frame buffer,简称fb)的硬件设备上进行渲染的
    SurfaceFlinger服务运行在Android系统的System进程中,它负责管理Android系统的帧缓冲区

    Surface类

    andorid是给出的解释是“Handle onto a raw buffer that is being managed by the screen compositor”,意思是surface是raw buffer的句柄,而且这个buffer是由screen compostior来管理的。raw buffer存储着当前窗口的像素数据,而screen compositor(屏幕合成器)目前不知道是什么鬼。既然Surface是raw buffer的句柄,那么我们就可以通过Surface对buffer进行操作(就像通过文件句柄读写文件一样),而buffer中存储着要显示的像素数据,那么最终我们可以通过Surface来控制屏幕上显示什么内容。

    那么Surface怎么使用呢?下面是Surcafe中的两个方法

    //Gets a Canvas for drawing into this surface.
    Canvas	lockCanvas(Rect inOutDirty)
    
    //Posts the new contents of the Canvas to the surface and releases the Canvas.
    unlockCanvasAndPost(Canvas canvas)
    

    第一个方法用来得到Canvas,然后我们在Canvas上画画(如果写过自定义View,那你对Canvas一定不会陌生),第二个方法就是将我们画好的画写到Surface中,对Surface的操作就这么简单。

    通常情况下,我们不会去创建一个Surface对象(Surface功能太少),而是通过创建SurfaceTexture或MediaRecorder这样的对象来创建Surface,这两个类内部会自动创建Surface对象,例如SurfaceTexture类的部分代码:

    public class SurfaceView extends View {
        .......
    
        final ArrayList<SurfaceHolder.Callback> mCallbacks
                = new ArrayList<SurfaceHolder.Callback>();
    
        final int[] mLocation = new int[2];
    
        final ReentrantLock mSurfaceLock = new ReentrantLock();
        final Surface mSurface = new Surface();       // Current surface in use
        final Surface mNewSurface = new Surface();    // New surface we are switching to
    
    	.......
    }
    

    而且我们也不会直接控制Sufrace,而是通过创建特定功能类(例如OpenGL, MediaPlayer, 或者CameraDevice)来向Surface中写数据。像MediaPlayer(音视频播放器)的使用,

    mediaPlayer.setDisPlay(surfaceView.getHolder());
    

    这里不会把surfaceView直接传进去,而是将其内部类SurfaceHolder传进去,可能是对surfaceView的保护吧

    SurfaceView

    上面已经介绍一部分SurfaceView,我们可以看出它她继承于View,而且它内置了一个surface。所以SurfaceView具有和其他的View(比如TextView)一样的特性,它会参与视图结构(View Hierarchy, View树)的绘制。但是它也有不同的地方,普通的View的都绘制在同一个绘图表面(Acitivity的Surface)上, 但是SurfaceView拥有自己的绘图表面,这样做的好处就是我们可以在子线程中更新SurfaceView中的内容。但是这样带来了一个问题,那就是不能对SurfaceView进行平移,缩放的操作。要更改一个控件的位置,大小,这个控件必须在主窗口(也就是Activity对应的窗口),但是SurfaceView用户自己的绘图表面,拥有自己的Window,我们更改SurfaceView将起不到任何作用。

    SurfaceView的简单使用
    class GameUI extends SurfaceView implements SurfaceHolder.Callback {
    
        private SurfaceHolder holder;
        private RenderThread renderThread;
        private boolean isDraw = false;// 控制绘制的开关
    
        public GameUI(Context context) {
            super(context);
            holder = this.getHolder();
            holder.addCallback(this);
            renderThread = new RenderThread();
        }
    
        /**
         *
         * @param holder
         * @param format
         * @param width
         * @param height
         */
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            isDraw = true;
            renderThread.start();
    
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            isDraw = false;
    
        }
    
        /**
         * 绘制界面的线程
         *
         * @author Administrator
         *
         */
        private class RenderThread extends Thread {
            @Override
            public void run() {
                // 不停绘制界面
                while (isDraw) {
                    drawUI();
                }
                super.run();
            }
        }
    
        /**
         * 界面绘制
         */
        public void drawUI() {
            Canvas canvas = holder.lockCanvas();
            try {
                drawCanvas(canvas);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                holder.unlockCanvasAndPost(canvas);
            }
        }
    
        private void drawCanvas(Canvas canvas) {
            // 在 canvas 上绘制需要的图形
        }
    }
    

    TextureView

    TextureView就是普通的

    参考

    SurfaceView

    http://www.cnblogs.com/wytiger/p/5693569.html
    http://blog.csdn.net/luoshengyang/article/details/8661317
    http://www.cnblogs.com/nicolaswang/p/3723089.html

    TextureView

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1213/2153.html
    http://blog.csdn.net/yanzi1225627/article/details/33313707

  • 相关阅读:
    PDF上添加水印
    java调用POI读取Excel
    搭建Linux的VMware Workstation Pro
    js中两种定时器的设置及清除
    SUI使用经验
    List集合与Array数组之间的互相转换
    jquery操作select
    jquery操作CheckBox
    时间格式
    java 获取路径的各种方法
  • 原文地址:https://www.cnblogs.com/xidongyu/p/7436468.html
Copyright © 2011-2022 走看看