效果图 难受
使用开源框架 DanmaKuView
先上布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <VideoView android:id="@+id/video" android:layout_width="match_parent" android:layout_height="match_parent" /> <master.flame.danmaku.ui.widget.DanmakuView android:id="@+id/dv" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="#fff" android:visibility="gone"> <EditText android:id="@+id/edit_text" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <Button android:id="@+id/send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="send"/> </LinearLayout> </RelativeLayout>
再来是逻辑
package com.example.yangzhan.danmu; import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; 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 static final String TAG = "MainActivity"; private VideoView mVideoView; private DanmakuView mDanmakuView; private DanmakuContext mDanmakuContext; private boolean showDanmaku; private EditText mEditText; private Button mButton; private LinearLayout mLinearLayout; private BaseDanmakuParser mParser=new BaseDanmakuParser() { @Override protected IDanmakus parse() { Log.d(TAG, "parse: "); return new Danmakus(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate: "); mVideoView = findViewById(R.id.video); mVideoView.setVideoURI(Uri.parse("android.resource://"+getPackageName()+"/"+R.raw.shusheng)); mVideoView.start(); mDanmakuView=findViewById(R.id.dv); mDanmakuView.enableDanmakuDrawingCache(true);//提升屏幕绘制效率 mDanmakuView.setCallback(new DrawHandler.Callback() { @Override public void prepared() { Log.d(TAG, "prepared: "); showDanmaku=true; mDanmakuView.start();//开始弹幕 generateSomeDanmaku(); } @Override public void updateTimer(DanmakuTimer timer) { Log.d(TAG, "updateTimer: "); } @Override public void danmakuShown(BaseDanmaku danmaku) { Log.d(TAG, "danmakuShown: "); } @Override public void drawingFinished() { Log.d(TAG, "drawingFinished: "); } }); mDanmakuContext=DanmakuContext.create(); mDanmakuView.prepare(mParser,mDanmakuContext); mLinearLayout=findViewById(R.id.ll); mButton=findViewById(R.id.send); mEditText=findViewById(R.id.edit_text); mDanmakuView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mLinearLayout.getVisibility()==View.GONE){ mLinearLayout.setVisibility(View.VISIBLE); }else { mLinearLayout.setVisibility(View.GONE); } } }); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String content = mEditText.getText().toString(); if(!TextUtils.isEmpty(content)){ addDanmaku(content,true); mEditText.setText(""); } } }); getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int i) { if(i==View.SYSTEM_UI_FLAG_VISIBLE){ onWindowFocusChanged(true); } } }); } @Override public void onWindowFocusChanged(boolean hasFocus) {//Activity得到或者失去焦点的时候 就会call。。得到焦点时 hasFocus = true super.onWindowFocusChanged(hasFocus); Log.d(TAG, "onWindowFocusChanged: hasFocus = "+hasFocus); if(hasFocus&& Build.VERSION.SDK_INT>=19){ View decorView = getWindow().getDecorView(); decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE //稳定布局,主要是在全屏和非全屏切换时,布局不要有大的变化 |View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION //将布局内容拓展到导航栏的后面 |View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //将布局内容拓展到状态的后面。 |View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //隐藏导航栏,点击屏幕任意区域,导航栏将重新出现,并且不会自动消失。 |View.SYSTEM_UI_FLAG_FULLSCREEN //隐藏状态栏,点击屏幕区域不会出现,需要从状态栏位置下拉才会出现。 |View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY //它在全屏模式下,用户上下拉状态栏或者导航栏时,这些系统栏只是以半透明的状态显示出来,并且在一定时间后会自动消息。 ); } } //随机生成弹幕 private void generateSomeDanmaku(){ new Thread(new Runnable() { @Override public void run() { while (showDanmaku){ int time = new Random().nextInt(300); String count="藤西 "+time+"号"; addDanmaku(count,false); try { Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } //添加一个新的弹幕 private void addDanmaku(String content,boolean with){ int r,g,b; BaseDanmaku danmaku = mDanmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);//创建弹幕对象 模式为从右至左 danmaku.text=content; //弹幕内容 danmaku.padding=5; danmaku.textSize=sp2px(20); Random random =new Random(); r = random.nextInt(256); g = random.nextInt(256); b = random.nextInt(256); danmaku.textColor= Color.rgb(r,g,b); danmaku.setTime(mDanmakuView.getCurrentTime()); if(with){ danmaku.borderColor=Color.RED; } mDanmakuView.addDanmaku(danmaku); } private int sp2px(float spValue){ float fontScale=getResources().getDisplayMetrics().scaledDensity; return (int) (spValue*fontScale+0.5f); } }
效果图 大致内容 注释都已经写好了