微信朋友圈短视频控件的实现, TextureView的基本使用。

本文介绍了TextureView的基本概念及其在Android应用中如何用于播放视频。TextureView专为绘制流内容设计,支持硬件加速并能更好地集成到ListView中。文中详细展示了如何结合TextureView和MediaPlayer实现一个简易的视频播放组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TextureView是什么?这个去看官方API文档比较好。

我这里简单总结下:

1.TextureView主要用来绘制流内容(比如视频,openGl场景)

2.TextureViewsurfaceView很相似,但是surfaceView是重新创建新窗口,这种方式效率高,但是不支持变化(旋转缩放等)操作,也很难再listview中使用,所以TextureView就弥补了这个缺点。

3.TextureView仅支持硬件加速,是通过GPU来绘制图形的。

 

TextureView简单用法

实现surfaceTextureListener,通过该接口的方法获得surfaceTexture

surfaceTexture是用来捕获来至cameravideo的图像流,如果获取不到surfaceTexture,那么TextureView就显示不了任何内容

Public methods

abstract void

onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)

Invoked when a TextureView's SurfaceTexture is ready for use.

abstract boolean

onSurfaceTextureDestroyed(SurfaceTexture surface)

Invoked when the specified SurfaceTexture is about to be destroyed.

abstract void

onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)

Invoked when the SurfaceTexture's buffers size changed.

abstract void

onSurfaceTextureUpdated(SurfaceTexture surface)

Invoked when the specified SurfaceTexture is updated through updateTexImage().

 

 

接下来结合MediaPlayer我们来实现短视频控件

以前用surfaceView来播放视频的时候可以获得surfaceHolder对象,然后通过setDisplay方法就可以为mediaplayer指定显示的surfaceview

但是textureview有点不同,他返回的是SurfaceTexture,这里我们需要先将SurfaceTexture转为Surface,然后通过setSurface方法为Mediaplayer指定显示的TextureView

 

VideoTextureView的代码:

public class VideoTextureView extends TextureView implements TextureView.SurfaceTextureListener {

    private MediaPlayer mediaPlayer;
    private Surface surface;
    private ImageView ivTip;
    private boolean isPlaying = false;
    private boolean isSurfaceTextureAvailable = false;
    private String videoPath;

    public VideoTextureView(Context context) {
        super(context);
        init(context);
    }

    public VideoTextureView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public VideoTextureView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        setSurfaceTextureListener(this);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
        surface = new Surface(surfaceTexture);
        isSurfaceTextureAvailable = true;
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
        surface=null;
        onVideoTextureViewDestroy();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

    }

    public void startMediaPlayer(){
        if(isPlaying || !isSurfaceTextureAvailable)
            return;
        if(TextUtils.isEmpty(videoPath)){
            ToastUtil.showMessage("视频路径异常", Toast.LENGTH_SHORT, true);
            return;
        }
        try {
            if(videoPath.equals(App.videoPath))
                mediaPlayer = MediaPlayer.create(getContext(), R.raw.test);
            else {
                final File file = new File(videoPath);
                if (!file.exists()) {//文件不存在
                    ToastUtil.showMessage("视频不存在", Toast.LENGTH_SHORT, true);
                    return;
                }
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setDataSource(file.getAbsolutePath());
            }
            mediaPlayer.setSurface(surface);
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setVolume(0, 0); //设置左右音道的声音为0
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp){
                    mediaPlayer.start();
                    showIvTip(false);
                    isPlaying = true;
                }
            });
            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mediaPlayer) {
                    stopMediaPlayer();
                }
            });
            mediaPlayer.prepare();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void showIvTip(boolean show){
        if(ivTip != null){
            int visibility = show?VISIBLE : GONE;
            ivTip.setVisibility(visibility);
        }
    }

    public void stopMediaPlayer(){
        if(mediaPlayer != null && isPlaying) {
            mediaPlayer.stop();
            mediaPlayer.reset();
        }
        showIvTip(true);
        isPlaying = false;
    }

    public void setIvTip(ImageView ivTip){
        this.ivTip = ivTip;
    }

    public boolean getPlayStatus(){
        return isPlaying;
    }

    public void setVideoPath(String path ){
        videoPath = path;
    }

    public void onVideoTextureViewDestroy(){
        isPlaying = false;
        if(mediaPlayer != null){
            stopMediaPlayer();
            mediaPlayer.release();
        }
    }
}

静态效果图

     



源码地址: https://github.com/zx391324751/weChatDemo   觉得可以的话,恳请各位帮忙给个星星.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值