简单的视频弹幕功能实现

我之前也是看博客写的,比较简单,思路比较清晰,我用了一个懒人框架,不用做findbyid以及监听事件

public class MainActivity extends Activity {
    @BindView(R.id.edit_text)
    EditText editText;
    @BindView(R.id.send)
    Button send;
    @BindView(R.id.operation_layout)
    LinearLayout operationLayout;
    /*DanmakuContext可以用于对弹幕的各种全局配置进行设定,如设置字体、设置最大显示行数等*/
    private DanmakuContext danmakuContext;
    private boolean showDanmaku;
    @BindView(R.id.video)
    VideoView video;/*视频播放器*/
    @BindView(R.id.activity_main)
    RelativeLayout activityMain;
    @BindView(R.id.danmaku_view)
    DanmakuView danmakuView;
    /*弹幕的解析器*/
    private BaseDanmakuParser parser = new BaseDanmakuParser() {
        @Override
        protected IDanmakus parse() {
            return new Danmakus();
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        /*设置了一个视频文件的地址*/
        video.setVideoPath(Environment.getExternalStorageDirectory() + "/Pixels.mp4");
        /*开始播放*/
        video.start();
        /*只是设置一些提升绘制效率,又调用了setCallback()方法来设置回调函数。*/
        danmakuView.enableDanmakuDrawingCache(true);
        danmakuView.setCallback(new DrawHandler.Callback() {
            @Override
            public void prepared() {
                showDanmaku = true;
                danmakuView.start();
                generateSomeDanmaku();
            }

            @Override
            public void updateTimer(DanmakuTimer timer) {

            }

            @Override
            public void danmakuShown(BaseDanmaku danmaku) {

            }

            @Override
            public void drawingFinished() {

            }
        });
        /*没有什么好设置的,直接默认就可以了*/
        danmakuContext = DanmakuContext.create();
        /*prepare()方法来进行准备*/
        danmakuView.prepare(parser, danmakuContext);
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(
                new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) {
                    onWindowFocusChanged(true);
                }
            }
        });

    }

    /*沉浸模式onWindowFocusChanged,就是为了让图片没有导航栏,如果是视频一般都是横向
    * 为了界面更好看*/
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        /*以下代码可以直接粘,这种模式5.0的系统才会有,
        所以要先做一个判断,然后在getWindow().getDecorView()方法获取到了当前界面的DecorView
        setSystemUiVisibility()设置他的可见性,下面的都是他的方法,详情百度
        http://blog.csdn.net/guolin_blog/article/details/51763825

         * */
        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);
        }
    }
    /*第3步在配置清单中,设置他的横屏,配置sd卡的权限*/
    /*第4步是弹幕的实现效果,这样可以用一个DanmakuFlameMaster
       先添加一个依赖app/build.gradle文件,并在dependencies闭包中添加如下依赖:
        compile 'com.github.ctiao:DanmakuFlameMaster:0.5.3'
        第5步可以在布局中引用了,有一点要记住DanmakuView写在VideoView的下面,
        因为RelativeLayout中后添加的控件会被覆盖在上面。

    * */

    /**DanmakuView已经在正常工作了,但是屏幕上没有任何弹幕信息的话我们也看不出效果,
     * 因此我们还要增加一个添加弹幕消息的功能。
     * 观察addDanmaku()方法,这个方法就是用于向DanmakuView中添加一条弹幕消息的
     * 向弹幕View中添加一条弹幕
     *
     * @param content    弹幕的具体内容
     * @param withBorder 弹幕是否有边框
     */
    private void addDanmaku(String content, boolean withBorder) {
        /*BaseDanmaku创建一个实例,TYPE_SCROLL_RL表示这是一条从右向左滚动的弹幕*/
        BaseDanmaku danmaku = danmakuContext.mDanmakuFactory.createDanmaku(BaseDanmaku.TYPE_SCROLL_RL);
       /*设置弹幕的颜色字体显示时间等等*/
        danmaku.text = content;
        danmaku.padding = 5;
        danmaku.textSize = sp2px(20);
        /*文字设成白色,*/
        danmaku.textColor = Color.WHITE;
        danmaku.setTime(danmakuView.getCurrentTime());
        /*是否带框*/
        if (withBorder) {
            danmaku.borderColor = Color.GREEN;
        }
        danmakuView.addDanmaku(danmaku);
    }

    /**
     * 随机生成一些弹幕内容以供测试
     */
    private void generateSomeDanmaku() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (showDanmaku) {
                    int time = new Random().nextInt(300);
                    String content = "" + time + time;
                    addDanmaku(content, false);
                    try {
                        Thread.sleep(time);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    /**
     * sp转px的方法。
     */
    public int sp2px(float spValue) {
        final float fontScale = getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }



    @OnClick(R.id.send)
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.send:
                String content = editText.getText().toString();
                if (!TextUtils.isEmpty(content)) {
                    addDanmaku(content, true);
                    editText.setText("");
                }
                break;
        }
    }

    /*DanmakuView设置了一个点击事件,当点击屏幕时就会触发这个点击事件。
    然后进行判断,如果操作界面是隐藏的就将它显示出来,
    如果操作界面是显示的就将它隐藏掉,这样就可以简单地通过点击屏幕来实现操作界面的隐藏和显示了。*/
    @OnClick(R.id.danmaku_view)
    public void onViewClicked() {
        if (operationLayout.getVisibility() == View.GONE) {
            operationLayout.setVisibility(View.VISIBLE);
        } else {
            operationLayout.setVisibility(View.GONE);
        }
        /*接下来我们又给发送按钮注册了一个点击事件,当点击发送时,
        获取EditText中的输入内容,然后调用addDanmaku()方法将这条消息添加到DanmakuView上。
        另外,这条弹幕是由我们自己发送的,因此addDanmaku()方法的第二个参数要传入true。
最后,由于系统输入法弹出的时候会导致焦点丢失,从而退出沉浸式模式,
因此这里还对系统全局的UI变化进行了监听,保证程序一直可以处于沉浸式模式。*/
        getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(
                new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        if (visibility == View.SYSTEM_UI_FLAG_VISIBLE) {
                            onWindowFocusChanged(true);
                        }
                    }
                });
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (danmakuView != null && danmakuView.isPrepared() && danmakuView.isPaused()) {
            danmakuView.resume();
        }
    }


    @Override
    protected void onPause() {
        super.onPause();
        if (danmakuView != null && danmakuView.isPrepared()) {
            danmakuView.pause();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        showDanmaku = false;
        if (danmakuView != null) {
            danmakuView.release();
            danmakuView = null;
        }
    }


}
------------------------------------------------------------------------------
 
<?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:id="@+id/activity_main"
    android:background="#000">
    <!--Videoview 本地视频播放器-->
    <VideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>
    <!--弹幕布局-->
    <master.flame.danmaku.ui.widget.DanmakuView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/danmaku_view"/>
    <LinearLayout
        android:id="@+id/operation_layout"
        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="match_parent"
            android:text="Send" />
    </LinearLayout>


</RelativeLayout>
----------------------------------------------------------------------------------
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<activity android:name=".MainActivity" android:screenOrientation="landscape"
    android:configChanges="orientation|keyboardHidden|screenLayout|screenSize">



 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值