Android dual surfaceview to achieve barrage effect
This example shares the specific code of Android dual surfaceview to realize the barrage effect for your reference. The specific contents are as follows
Page layout
The first is the layout of XML. The general parent layout here is a FrameLayout for pasting two surfaceviews, one for playing video and one for displaying bullet screen
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".DanmuActivity"> <SurfaceView android:id="@+id/sv_text" android:layout_width="match_parent" android:layout_height="400dp"/> <SurfaceView android:id="@+id/sv_media" android:layout_width="match_parent" android:layout_height="400dp"/> /> <EditText android:id="@+id/et_text" android:layout_width="300dp" android:layout_height="wrap_content" android:layout_marginTop="450dp"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送" android:layout_marginTop="500dp" android:onClick="Gogo"/> </FrameLayout>
Object class
Create an object class to store the barrage you send
public class Danmu { String text;//弹幕内容 int x;//x轴 int y;//y轴 public Danmu(String text){ this.text = text; //将y设置为随机,弹幕出现的位置也为随机 this.y = (int) (Math.random()*400); this.x = 0; } }
The activity implements surfaceholder.callback and rewrites its method
First define what you need and play the video. We use mediaplayer
//视频播放 private MediaPlayer mediaPlayer; //弹幕Surface与视频Surface private SurfaceView sv_text,sv_media; //两个Surface对应的两个holder private SurfaceHolder text_holder,media_holder; EditText editText;//字幕输入框 List<Danmu> list = new ArrayList<>();//存放
Initialize mediaplayer in the first step, otherwise it will be empty when running. It is encapsulated into a method and called directly in oncreate
private void initPlayer() throws IOException { //先判断是否创建过,没创建就创建出来 if (mediaPlayer == null) { mediaPlayer = new MediaPlayer(); } mediaPlayer.reset();//使其恢复空闲状态 //播放的资源 mediaPlayer.setDataSource("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"); mediaPlayer.prepare();//准备 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) {//准备完毕了 mediaPlayer.start();//播放 } }); }
Initialize the control, which is also encapsulated as a method, and the holder obtains it with the corresponding surface
private void initView() { sv_text = findViewById(R.id.sv_text); text_holder = sv_text.getHolder(); text_holder.addCallback(this); sv_media = findViewById(R.id.sv_media); media_holder = sv_media.getHolder(); media_holder.addCallback(this); editText = findViewById(R.id.et_text); //设置透明,将播放弹幕的Surface放到第一位并设置为背景透明 sv_text.setZOrderOnTop(true); text_holder.setFormat(PixelFormat.TRANSPARENT); }
Next is the method overridden by surface.callback
@Override public void surfaceCreated(SurfaceHolder holder) { //判断当前holder是否是media的那个 if (holder == media_holder) { //设置要显示的Surfaceholder mediaPlayer.setDisplay(media_holder); //判断当前holder是否是字幕的那个 } else if (holder == text_holder) { //创建线程执行耗时操作 new Thread() { @Override public void run() { super.run(); //死循环用来一直更新弹幕的位置 while (true) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Paint paint = new Paint();//创建画笔 paint.setstrokeWidth(5);//画笔粗细 paint.setColor(Color.GREEN);//画笔颜色 paint.setTextSize(30);//设置文字大小 //创建画板 Canvas canvas = text_holder.lockCanvas(); //判断若画板为空则跳出循环 if (canvas == null) { break; } //设置画布颜色,透明 canvas.drawColor(PixelFormat.TRANSPARENT,PorterDuff.Mode.CLEAR); //用循环来你的弹幕集合并且在画板上展示出来 //x+=20为你的弹幕在不断的从左到右移动 for (Danmu danmu : list) { canvas.drawText(danmu.text,danmu.x += 20,danmu.y,paint); //若移动的位置大于视频Surface的宽度了就归0 if (danmu.x > sv_media.getWidth()) { danmu.x = 0; } } //将画布解锁并显示到屏幕上 text_holder.unlockCanvasAndPost(canvas); } } }.start();//不要忘记开启线程 } }
Button click event sent
public void Gogo(View view) { //先判断输入框里有没有东西 if (!editText.getText().toString().isEmpty() && !editText.getText().toString().equals("")) { Danmu danmu = new Danmu(editText.getText().toString()); list.add(danmu); } }
The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.