本文实例为大家分享了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