Android 控件之TextureView详解手机开发

TextureView在4.0(API level 14)中引入的,它可以将内容流直接投影到View中,可以用于实现Live preview等功能。和SurfaceView不同,它不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。例如,将TextureView设置成半透明。值得注意的是TextureView必须在硬件加速的窗口中。

myView.setAlpha(0.5f)

TextureView的继承层次如下图所示:
这里写图片描述
从类图中可以看到,TextureView继承自View,它与其它的View一样在View hierachy中管理与绘制。TextureView重载了draw()方法,其中主要把SurfaceTexture中收到的图像数据作为纹理更新到对应的HardwareLayer中。SurfaceTexture.OnFrameAvailableListener用于通知TextureView内容流有新图像到来。SurfaceTextureListener接口用于让TextureView的使用者知道SurfaceTexture已准备好,这样就可以把SurfaceTexture交给相应的内容源。Surface为BufferQueue的Producer接口实现类,使生产者可以通过它的软件或硬件渲染接口为SurfaceTexture内部的BufferQueue提供graphic buffer。

关于TextureView更多的介绍可以通过Textureview 官方API来了解。

SurfaceView

应用程序的视频或者opengl内容往往是显示在一个特别的UI控件中:SurfaceView。SurfaceView的工作方式是创建一个置于应用窗口之后的新窗口。这种方式的效率非常高,因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下,不过满足普通应用界面的需求还是绰绰有余)。
但是SurfaceView也有一些非常不便的限制,因为SurfaceView的内容不在应用窗口上,所以不能使用变换(平移、缩放、旋转等)。也难以放在ListView或者ScrollView中,不能使用UI控件的一些特性比如View.setAlpha()。

实例

例如,下面是使用MediaPlayer和TextureView实现视频播放的实例。注意TextureView中的draw方法和onDraw方法都是被定义成final的,不能被子类覆盖。所以必须可以通过实现TextureView.SurfaceTextureListener 接口,然后重写onSurfaceTextureAvailable方法。下面是具体的代码:

public class MainView extends TextureView implements TextureView.SurfaceTextureListener { 
    private static final String FILE_NAME = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"; 
 
    private MediaPlayer mMediaPlayer; 
 
 
    public MainView(Context context) { 
        super(context); 
        initView(); 
 
    } 
 
    public void stopPlay() { 
        if (mMediaPlayer != null) { 
            mMediaPlayer.stop(); 
            mMediaPlayer.release(); 
            mMediaPlayer = null; 
        } 
 
    } 
 
    private void initView() { 
        setSurfaceTextureListener(this); 
 
    } 
 
    @Override 
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) { 
 
        Surface surface = new Surface(surfaceTexture); 
        try { 
 
            mMediaPlayer = new MediaPlayer(); 
            mMediaPlayer.setDataSource(FILE_NAME); 
            mMediaPlayer.setSurface(surface); 
            mMediaPlayer.prepareAsync(); 
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
                @Override 
                public void onPrepared(MediaPlayer mp) { 
                    mMediaPlayer.start(); 
                } 
            }); 
 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
 
    } 
 
    @Override 
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) { 
    } 
 
    @Override 
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { 
        return true; 
    } 
 
    @Override 
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { 
    } 
}

对应的activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="176dp" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context=".MainActivity"> 
 
    <com.test.xingliu.texturesample.MainView 
        android:id="@+id/textureView" 
        android:layout_width="match_parent" 
        android:layout_height="176dp" 
        android:orientation="vertical" 
        android:paddingBottom="@dimen/activity_vertical_margin" 
        android:paddingLeft="@dimen/activity_horizontal_margin" 
        android:paddingRight="@dimen/activity_horizontal_margin" /> 
 
 
</LinearLayout>

这里写图片描述

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5522.html

(0)
上一篇 2021年7月16日
下一篇 2021年7月16日

相关推荐

发表回复

登录后才能评论