Android Double SurfaceView to achieve barrage effect

  • 2021-11-14 06:59:21
  • OfStack

In this paper, we share the specific code of Android double SurfaceView barrage effect for your reference. The specific contents are as follows

Page layout

The first is the layout layout of XML. The general parent layout here is one FrameLayout for pasting two SurfaceView, one for playing video and one for displaying barrage


<?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=" Send "
    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;// Barrage content 
  int x;//x Shaft 
  int y;//y Shaft 

  public Danmu(String text){
    this.text = text;
    // Will y Set to random , The location of the barrage is also random 
    this.y = (int) (Math.random()*400);
    this.x = 0;
  }
}

Activity implements SurfaceHolder. Callback and overrides its methods

First define what you need, and play the video. We use Mediaplayer


// Video playback 
private MediaPlayer mediaPlayer;
// Barrage Surface And video Surface
private SurfaceView sv_text, sv_media;
// Two Surface Corresponding two holder
private SurfaceHolder text_holder, media_holder;
EditText editText;// Subtitle input box 
List<Danmu> list = new ArrayList<>();// Storage 

Initialize MediaPlayer, if you want to execute it in step 1, otherwise it will report empty. Here, it is encapsulated as a method, which is called directly in onCreate


private void initPlayer() throws IOException {
 // First determine whether it has been created , Create it without creating it 
    if (mediaPlayer == null) {
      mediaPlayer = new MediaPlayer();
    }
    mediaPlayer.reset();// Restore it to its idle state 
    // Played resources 
    mediaPlayer.setDataSource("http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4");
    mediaPlayer.prepare();// Prepare 
    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
      @Override
      public void onPrepared(MediaPlayer mp) {// It's ready 
        mediaPlayer.start();// Play 
      }
    });
  }

Initialize the control, which is also encapsulated as a method. holder is obtained by 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);

    // Setting Transparency , The that will play the barrage Surface Put it in the first place 1 Bit and set to background transparency 
    sv_text.setZOrderOnTop(true);
    text_holder.setFormat(PixelFormat.TRANSPARENT);
  }

Next is the Surface. Callback override method


@Override
  public void surfaceCreated(SurfaceHolder holder) {
  // Judge the current holder Whether it is media The one of 
    if (holder == media_holder) {
    // To set the Surfaceholder
      mediaPlayer.setDisplay(media_holder);
        // Judge the current holder Is it the one with subtitles 
    } else if (holder == text_holder) {
    // Create a thread to perform a time-consuming operation 
      new Thread() {
        @Override
        public void run() {
          super.run();
          // An infinite loop is used 1 Update the location of the barrage directly 
          while (true) {
            try {
              Thread.sleep(500);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
  Paint paint = new Paint();// Create a brush 
 paint.setStrokeWidth(5);// Brush thickness 
 paint.setColor(Color.GREEN);// Brush color 
  paint.setTextSize(30);// Set the text size 
 // Create Sketchpad 
   Canvas canvas = text_holder.lockCanvas();
   // Judge that if the drawing board is empty, jump out of the loop 
            if (canvas == null) {
              break;
            }
        // Set Canvas Color , Transparency 
 canvas.drawColor(PixelFormat.TRANSPARENT, PorterDuff.Mode.CLEAR);
 // Loop your barrage collection and show it on the drawing board 
 //x+=20 For your barrage is constantly moving from left to right 
      for (Danmu danmu : list) {
  canvas.drawText(danmu.text, danmu.x += 20, danmu.y, paint);
  // If the moving position is larger than the video Surface The width of the return 0
     if (danmu.x > sv_media.getWidth()) {
                danmu.x = 0;
           }
          }
          // Unlock the canvas and display it on the screen 
    text_holder.unlockCanvasAndPost(canvas);
          }
        }
      }.start();// Don't forget to open the thread 

    }

  }

Click event of the button sent


public void Gogo(View view) {
// First judge if there is anything in the input box 
    if (!editText.getText().toString().isEmpty() && !editText.getText().toString().equals("")) {
      Danmu danmu = new Danmu(editText.getText().toString());
      list.add(danmu);
    }
  }

Related articles: