服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - SurfaceView播放视频发送弹幕并实现滚动歌词

SurfaceView播放视频发送弹幕并实现滚动歌词

2022-11-09 15:27职业大坑 Android

这篇文章主要为大家详细介绍了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); ——背景透明

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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卡读写权限!!!!!

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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);
      }
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/caoqijia123/article/details/96356895

延伸 · 阅读

精彩推荐