Android realizes video barrage function
This example shares the specific code of Android video barrage for your reference. The specific contents are as follows
design sketch:
Above: barrage randomly generated by code and barrage input field
The following figure: the bullet screen in the green box is the bullet screen manually added and sent by the user
1. Preparation
Prepare a video file and put it in the RES / raw directory.
You need to set the video to play horizontally, that is, add Android: screenorientation = "landscape" to the configuration file:
<activity android:name=".MainActivity" android:configChanges="keyboardHidden|orientation|screenLayout|screenSize" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
The open source barrage effect library danmakuflamemaster of BiliBili is used here. It needs to be configured in the dependencies of the module build.gradle
Note: it is better to use the version of danmaku flamemaster above 0.9, otherwise there will be some barrage bugs
2. Layout
Using a relative layout, the bullet screen floats above the video, the bullet screen text input field is at the bottom, and the bullet screen send button is at the lower right corner:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000"> <VideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"/> <master.flame.danmaku.ui.widget.DanmakuView android:id="@+id/danmu" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/operate_layout" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:visibility="gone"> <EditText android:id="@+id/edit" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginLeft="50dp" android:textColor="#ffffff" android:imeOptions="flagNoExtractUi" /> <Button android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/send" android:textSize="20sp" android:background="#00000000" android:textColor="#ffffff" android:text="发送"/> </LinearLayout> </RelativeLayout>
3. Realization of video barrage
<1> Play video using videoview;
<2> about bullet screen comments, we need to create an instance of DanmakuContext and a bullet screen comments (which directly creates a global BaseDanmakuParser). After creating, we can call DanmakuView's prepare () method. After calling this method, we will call the prepared () method in callback function automatically. In this method, we call start method. The barrage began to work;
<3> You need to perform some operations in onpause(), onresume(), ondestroy() methods to ensure that danmakuview's resources can be released.
The complete code is attached below
package com.mega.mydanmudemo; import android.content.Context; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.VideoView; import java.util.Random; import master.flame.danmaku.controller.DrawHandler; import master.flame.danmaku.danmaku.model.BaseDanmaku; import master.flame.danmaku.danmaku.model.DanmakuTimer; import master.flame.danmaku.danmaku.model.IDanmakus; import master.flame.danmaku.danmaku.model.android.DanmakuContext; import master.flame.danmaku.danmaku.model.android.Danmakus; import master.flame.danmaku.danmaku.parser.BaseDanmakuParser; import master.flame.danmaku.ui.widget.DanmakuView; public class MainActivity extends AppCompatActivity { private boolean showDanma; private VideoView mVideoView; private DanmakuView mDanmu; private BaseDanmakuParser mBaseDanmakuParser = new BaseDanmakuParser() {//弹幕解析器 @Override protected IDanmakus parse() { return new Danmakus(); } }; private DanmakuContext danmakuContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); setOnListener(); } /*** * 一些初始化工作 */ private void init() { String uri = "android.resource://" + getPackageName() + "/" + R.raw.danmu; mVideoView = (VideoView)findViewById(R.id.video_view); mVideoView.setVideoPath(uri); mVideoView.start(); mDanmu = (DanmakuView)findViewById(R.id.danmu); mDanmu.enableDanmakuDrawingCache(true); danmakuContext = DanmakuContext.create(); danmakuContext.setScaleTextSize(1.1f); mDanmu.prepare(mBaseDanmakuParser,danmakuContext); } /*** * 弹幕的准备工作,发送按钮监听。。 */ private void setOnListener(){ mDanmu.setCallback(new DrawHandler.Callback() { @Override public void prepared() { showDanma = true; mDanmu.start();//启动弹幕 generateSomeDanmu(); } @Override public void updateTimer(DanmakuTimer timer) { } @Override public void danmakuShown(BaseDanmaku danmaku) { } @Override public void drawingFinished() { } }); final LinearLayout operate_view = (LinearLayout)findViewById(R.id.operate_layout); Button send = (Button)findViewById(R.id.send); final EditText editText = (EditText)findViewById(R.id.edit); mDanmu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (operate_view.getVisibility() == View.GONE){ operate_view.setVisibility(View.VISIBLE); }else{ operate_view.setVisibility(View.GONE); } } }); send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String content = editText.getText().toString(); if (!TextUtils.isEmpty(content)){ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(),0); addDamu(content,true); editText.setText(""); operate_view.setVisibility(View.GONE); } } }); getWindow().getDecorView().setOnsystemUIVisibilitychangelistener(new View.OnsystemUIVisibilitychangelistener() { @Override public void onsystemUIVisibilityChange(int visibility) { if (visibility == View.SYstem_UI_FLAG_VISIBLE){ onWindowFocusChanged(true); } } }); } /*** * 随机产生一些弹幕 */ private void generateSomeDanmu() { new Thread(new Runnable() { @Override public void run() { while (showDanma){ int time = new Random().nextInt(300); String content = "" + time; addDamu(content,false); try { Thread.sleep(time); }catch (Exception e){ e.printStackTrace(); } } } }).start(); } /*** * 添加弹幕的方法 * @param content 弹幕的内容 * @param isSelf 是否是用户发送的弹幕 */ private void addDamu(String content,boolean isSelf) { BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL); danmaku.text = content; danmaku.padding = 5; danmaku.priority = 0; danmaku.textSize = sp2px(20); danmaku.setTime(mDanmu.getCurrentTime()); danmaku.textColor = Color.argb(new Random().nextInt(256),new Random().nextInt(256),new Random().nextInt(256)); if (isSelf){ danmaku.borderColor = Color.GREEN; } mDanmu.addDanmaku(danmaku); } private float sp2px(int i) { final float fontScale = getResources().getDisplayMetrics().scaledDensity; return (int)(i* fontScale +0.5f); } @Override protected void onPause() { super.onPause(); if (mDanmu!= null && mDanmu.isPrepared()){ mDanmu.pause(); } } @Override protected void onResume() { super.onResume(); if (mDanmu!=null&& mDanmu.isPrepared()&& mDanmu.isPaused()){ mDanmu.resume(); } } @Override protected void onDestroy() { super.onDestroy(); showDanma = false; if (mDanmu != null){ mDanmu.release(); mDanmu = null; } } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus && Build.VERSION.SDK_INT>=19){ View deview = getWindow().getDecorView(); deview.setsystemUIVisibility(View.SYstem_UI_FLAG_LAYOUT_STABLE |View.SYstem_UI_FLAG_HIDE_NAVIGATION |View.SYstem_UI_FLAG_FULLSCREEN |View.SYstem_UI_FLAG_LAYOUT_HIDE_NAVIGATION |View.SYstem_UI_FLAG_LAYOUT_FULLSCREEN |View.SYstem_UI_FLAG_IMMERSIVE_STICKY); } } }
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.