SurfaceView播放视频发送弹幕并实现滚动歌词
作者:职业大坑
这篇文章主要为大家详细介绍了SurfaceView播放视频发送弹幕并实现滚动歌词,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
本文实例为大家分享了SurfaceView播放视频发送弹幕,并实现滚动歌词,供大家参考,具体内容如下
SurfaceView使用步骤
使用SurfaceView的步骤:
- 首先要继承SurfaceView,实现SurfaceHolder.Callback接口。
- 重写方法:surfaceChanged:surface大小或格式发生变化时触发,在surfaceCreated调用后该函数至少会被调用一次。
- surfaceCreated:Surface创建时触发,一般在这个函数开启绘图线程(新的线程,不要再这个线程中绘制Surface)。
- surfaceDestroyed:销毁时触发,一般不可见时就会销毁。
- 利用getHolder()获取SurfaceHolder对象,调用SurfaceHolder.addCallback添加回调
- SurfaceHolder.lockCanvas 获取Canvas对象并锁定画布,调用Canvas绘图,SurfaceHolder.unlockCanvasAndPost 结束锁定画布,提交改变。
SurfaceHolder
SurfaceHolder回调自己的三个生命周期:
- surfaceCreated(SurfaceHolder holder)创建时
- surfaceChanged(SurfaceHolder holder, int format, int width, int height)改变时
- surfaceDestroyed(SurfaceHolder holder)销毁时
SurfaceView播放视频并可以发送弹幕
需要准备两个SurfaceView,一个是负责播放视频,一个负责展示弹幕。弹幕是展示在视频上面的,所以我们要给展示弹幕的SurfaceView设置两个方法:
surfaceView_danmu.setZOrderOnTop(true); ——置于上方
surfaceView_danmuHolder.setFormat(PixelFormat.TRANSPARENT); ——背景透明
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback { public static final int PROGRESS = 101; SurfaceView surfaceView,surfaceView_danmu; SurfaceHolder surfaceHolder,surfaceView_danmuHolder; MediaPlayer mediaPlayer = new MediaPlayer(); String path = "/sdcard/aa.mp4"; SeekBar seekBar; Timer timer; EditText editText; Button button,bt_start,bt_stop; int x = 0; ArrayList<DanMu> list = new ArrayList<>(); Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == PROGRESS){ seekBar.setProgress((Integer) msg.obj); mediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() { @Override public void onSeekComplete(MediaPlayer mp) { Toast.makeText(MainActivity.this, "播放完毕!", Toast.LENGTH_SHORT).show(); } }); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceView = findViewById(R.id.sufaceview); surfaceView_danmu = findViewById(R.id.sufaceview_danmu); editText = findViewById(R.id.et); button = findViewById(R.id.bt_send); seekBar = findViewById(R.id.bar); bt_start = findViewById(R.id.bt_start); bt_stop = findViewById(R.id.bt_stop); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); surfaceView_danmuHolder = surfaceView_danmu.getHolder(); surfaceView_danmuHolder.addCallback(this); surfaceView_danmu.setZOrderOnTop(true); surfaceView_danmuHolder.setFormat(PixelFormat.TRANSPARENT); if (mediaPlayer!=null) { try { mediaPlayer.setDataSource(path); mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start(); int duration = mediaPlayer.getDuration(); seekBar.setMax(duration); timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { int currentPosition = mediaPlayer.getCurrentPosition(); Message message = Message.obtain(); message.what = PROGRESS; message.obj = currentPosition; handler.sendMessage(message); } },0,1000); } }); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { int progress = seekBar.getProgress(); mediaPlayer.seekTo(progress); } }); } catch (IOException e) { e.printStackTrace(); } } button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String s = editText.getText().toString(); int y= (int) (Math.random()*300); list.add(new DanMu(0,y,s,Color.RED)); } }); bt_start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mediaPlayer.start(); } }); bt_stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mediaPlayer.pause(); } }); } @Override public void surfaceCreated(SurfaceHolder holder) { if (holder == surfaceHolder) { mediaPlayer.setDisplay(holder); }else if (holder == surfaceView_danmuHolder) { new MyDanMuThread().start(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } class MyDanMuThread extends Thread { @Override public void run() { super.run(); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setTextSize(40); while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } Canvas canvas = surfaceView_danmuHolder.lockCanvas(); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); for (int i=0;i<list.size();i++) { DanMu danMu = list.get(i); x = danMu.getX(); danMu.setX(x+=10); canvas.drawText(danMu.getText(),danMu.getX(),danMu.getY(),paint); } surfaceView_danmuHolder.unlockCanvasAndPost(canvas); } } } }
实现滚动歌词
要准备一个装有时间和歌词的集合,准备一个Timer计时器和一个该展示第几个歌词。每隔一秒去拿该歌词的下一个歌词时间与进度匹配,如果进度>=该时间,那么就画该歌词在SurfaceView上;<则不画该歌词
一定要写SD卡读写权限!!!!!
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{ SurfaceView surfaceView; SurfaceHolder surfaceHolder; MediaPlayer mediaPlayer = new MediaPlayer(); ArrayList<Music> list=new ArrayList<>(); Timer timer; int count = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceView = findViewById(R.id.sv); surfaceHolder=surfaceView.getHolder(); surfaceHolder.addCallback(this); timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { int currentPosition = mediaPlayer.getCurrentPosition(); if(list.size()>0){ if(currentPosition>=list.get(count+1).getTime()){ count++; } } } },0,500); try { mediaPlayer.setDataSource("/sdcard/凤凰传奇 - 最炫民族风(Live).mp3"); mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start(); } }); } catch (IOException e) { e.printStackTrace(); } try { StringBuffer stringBuffer = new StringBuffer(); FileInputStream fileInputStream = new FileInputStream("/sdcard/最炫民族风"); byte[] bytes = new byte[1024]; int len = 0; while ((len=fileInputStream.read(bytes))!=-1) { stringBuffer.append(new String(bytes,0,len)); } Gson gson = new Gson(); JavaBean javaBean = gson.fromJson(stringBuffer.toString(), JavaBean.class); JavaBean.LrcBean lrc = javaBean.getLrc(); String lyric = lrc.getLyric(); String[] split = lyric.split("\n"); for(int i=0;i<split.length;i++){ String trim = split[i].trim(); String[] split1 = trim.split("]"); if(split.length>=2){ String s = split1[0]; String substring1 = s.substring(1, 3); String substring2 = s.substring(4, 6); String substring3 = s.substring(7, 10); long start = Integer.parseInt(substring1)*60*1000+Integer.parseInt(substring2)*1000+Integer.parseInt(substring3); String text = split1[1]; list.add(new Music(text,start)); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceCreated(SurfaceHolder holder) { new MyThread().start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } class MyThread extends Thread { @Override public void run() { super.run(); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setTextSize(50); while (true){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Canvas canvas = surfaceHolder.lockCanvas(); if(canvas==null){ break; } canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); if(list.size()>0){ canvas.drawText(list.get(count).getTitle(),100,100,paint); } surfaceHolder.unlockCanvasAndPost(canvas); } } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。