最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SurfaceView播放視頻發(fā)送彈幕并實現(xiàn)滾動歌詞

 更新時間:2019年11月28日 09:26:44   作者:職業(yè)大坑  
這篇文章主要為大家詳細介紹了SurfaceView播放視頻發(fā)送彈幕并實現(xiàn)滾動歌詞,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了SurfaceView播放視頻發(fā)送彈幕,并實現(xiàn)滾動歌詞,供大家參考,具體內(nèi)容如下

SurfaceView使用步驟

使用SurfaceView的步驟:

  • 首先要繼承SurfaceView,實現(xiàn)SurfaceHolder.Callback接口。
  • 重寫方法:surfaceChanged:surface大小或格式發(fā)生變化時觸發(fā),在surfaceCreated調(diào)用后該函數(shù)至少會被調(diào)用一次。
  • surfaceCreated:Surface創(chuàng)建時觸發(fā),一般在這個函數(shù)開啟繪圖線程(新的線程,不要再這個線程中繪制Surface)。
  • surfaceDestroyed:銷毀時觸發(fā),一般不可見時就會銷毀。
  • 利用getHolder()獲取SurfaceHolder對象,調(diào)用SurfaceHolder.addCallback添加回調(diào)
  • SurfaceHolder.lockCanvas 獲取Canvas對象并鎖定畫布,調(diào)用Canvas繪圖,SurfaceHolder.unlockCanvasAndPost 結束鎖定畫布,提交改變。

SurfaceHolder

SurfaceHolder回調(diào)自己的三個生命周期:

  • surfaceCreated(SurfaceHolder holder)創(chuàng)建時
  • surfaceChanged(SurfaceHolder holder, int format, int width, int height)改變時
  • surfaceDestroyed(SurfaceHolder holder)銷毀時

SurfaceView播放視頻并可以發(fā)送彈幕

需要準備兩個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);
      }
    }
  }
}

實現(xiàn)滾動歌詞

要準備一個裝有時間和歌詞的集合,準備一個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);
      }
    }
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • 完美解決安卓jni項目會刪除其他so文件的問題

    完美解決安卓jni項目會刪除其他so文件的問題

    下面小編就為大家?guī)硪黄昝澜鉀Q安卓jni項目會刪除其他so文件的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • 雙緩沖技術實現(xiàn)Android 畫板應用

    雙緩沖技術實現(xiàn)Android 畫板應用

    這篇文章主要介紹了Android 采用雙緩存技術實現(xiàn)畫板應用的相關資料,并附有代碼實例,有需要的小伙伴可以參考下
    2016-07-07
  • Android向node.js編寫的服務器發(fā)送數(shù)據(jù)并接收請求

    Android向node.js編寫的服務器發(fā)送數(shù)據(jù)并接收請求

    這篇文章主要為大家詳細介紹了Android向node.js編寫的服務器發(fā)送數(shù)據(jù),并接收請求,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android基礎控件RadioGroup使用方法詳解

    Android基礎控件RadioGroup使用方法詳解

    這篇文章主要為大家詳細介紹了Android基礎控件RadioGroup的使用方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 詳解Android App中ViewPager使用PagerAdapter的方法

    詳解Android App中ViewPager使用PagerAdapter的方法

    這篇文章主要介紹了詳解Android App中ViewPager使用PagerAdapter的方法,同時附帶了一個ViewPager的PagerAdapter不能更新數(shù)據(jù)的問題解決方法,需要的朋友可以參考下
    2016-03-03
  • Android View滑動的實現(xiàn)分析示例

    Android View滑動的實現(xiàn)分析示例

    View滑動是Android實現(xiàn)自定義控件的基礎,同時在開發(fā)中難免會遇到View的滑動處理,其實不管是那種滑動方法,基本思路是類似的;當點擊事件傳到View時,系統(tǒng)記下觸摸點的坐標,手指移動時系統(tǒng)記下移動后的左邊并算出偏移量,通過偏移量來修改View的坐標
    2022-08-08
  • Android 監(jiān)聽應用前/后臺切換實例代碼

    Android 監(jiān)聽應用前/后臺切換實例代碼

    本篇文章主要介紹了Android 監(jiān)聽應用前/后臺切換實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Android studio 混淆+打包+驗證是否成功

    Android studio 混淆+打包+驗證是否成功

    本文主要介紹了Android studio 混淆+打包+驗證是否成功的相關知識,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • Android實現(xiàn)多媒體錄音筆

    Android實現(xiàn)多媒體錄音筆

    這篇文章主要介紹了Android實現(xiàn)多媒體錄音筆的相關資料,以及在實現(xiàn)過程中遇到問題的解決方法,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Android開發(fā)之MediaPlayer基本使用方法詳解

    Android開發(fā)之MediaPlayer基本使用方法詳解

    這篇文章主要介紹了Android開發(fā)之MediaPlayer基本使用方法,結合實例形式較為詳細的分析了MediaPlayer中的常用函數(shù)與基本使用技巧,需要的朋友可以參考下
    2017-05-05

最新評論

天水市| 蓬莱市| 田阳县| 梧州市| 淄博市| 海晏县| 唐海县| 额敏县| 昌都县| 安徽省| 神木县| 乃东县| 湖北省| 屯留县| 博罗县| 长兴县| 冀州市| 修武县| 河间市| 紫金县| 抚宁县| 武陟县| 临桂县| 泸水县| 横山县| 肥乡县| 光山县| 循化| 龙游县| 宣汉县| 伊宁县| 西城区| 迁西县| 克拉玛依市| 临海市| 内乡县| 遂宁市| 砚山县| 双江| 陇川县| 东山县|