安卓Android弹幕功能实现-使用SurfaceView

先来一张效果图

安卓Android弹幕实现-思路

每一条弹幕其实都是一个文本,用drawText即可绘制,我们可以建立一个集合用来存储弹幕,动态改变弹幕的X轴,即可移动弹幕,当弹幕移出屏幕时,再进行销毁操作。

下面我们一步一步来实现弹幕效果:

第一步:新建mSurfaceView类,继承SurfaceView,并实现SurfaceHolder.Callback以及Runnable接口

 
public class mSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{@Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {}@Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}@Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {Flag=false;} @Override
    public void run() { }
}

第二步:定义如下成员变量,并实现构造方法:

//用于标注线程是否继续
private boolean Flag=true;//SurfaceHolder
SurfaceHolder surfaceHolder;//弹幕的集合
public List<mText> Barrages=new ArrayList<>();//用于随机生成弹幕的Y轴坐标
Random random=new Random();public mSurfaceView(Context context) {super(context);
}public mSurfaceView(Context context, AttributeSet attrs) {super(context, attrs);surfaceHolder=getHolder();surfaceHolder.addCallback(this);//设置背景透明
    this.setZOrderOnTop(true);surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
}public mSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
}

前面说过,每一条弹幕都需要存入集合,绘制的时候再遍历集合取出里面的弹幕进行绘制,那下面第三步:添加弹幕类

public class mText {//文字
    private String text;//文字大小
    private float size;//文字颜色
    private Integer color;//文字X轴
    private float x;//文字Y轴
    private float y;//文字移动速度
    private int speed;//画笔
    private Paint paint;public String getText() {return text;}public void setText(String text) {this.text = text;}public float getSize() {return size;}public void setSize(float size) {this.size = size;}public Integer getColor() {return color;}public void setColor(Integer color) {this.color = color;}public float getX() {return x;}public void setX(float x) {this.x = x;}public float getY() {return y;}public void setY(float y) {this.y = y;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}public Paint getPaint() {return paint;}public void setPaint(Paint paint) {this.paint = paint;}}

疑问:

其实大家可能注意到,上方弹幕类中,定义有文字内容、文字颜色、文字大小等成员变量,既然有颜色、大小等,那我们为什么还有定义画笔呢?

其实画笔可以传一个null,考虑到有时候仅靠颜色和大小可能无法完全满足我们的需求,所以我们可以定义一个画笔,更方便扩展,如果传过来了画笔,则直接用画笔进行绘制,如果画笔为null,则用默认的画笔,通过类中的颜色、大小等进行绘制。

既然已经定义弹幕类,那肯定也需要添加弹幕到弹幕集合的方法,第四步:定义add方法:

//添加弹幕
public void add(mText mText) {if (mText.getX()==0){mText.setX(getWidth());}if (mText.getY()==0){int i=getHeight();if (i>0){mText.setY(random.nextInt(i));}}Barrages.add(mText);
}

大家看到,上面有对x和y轴参数的非空判断,这样做的目的是当我们在调用add方法时,可以不给mText类的x、y赋值,节省我们的时间,如果检测到y轴为0,就随机指定一个y轴,如果x轴为0,则默认从屏幕的最右侧开始。

截止目前,准备工作已经做完,下面我们开始绘制:

@Override
public void run() {Canvas canvas=null;mText mtext = null;Paint paint=null;while (Flag){//如果集合为0,则跳过本次循环
        if (Barrages.size()==0){continue;}try {//获取画布
            canvas=surfaceHolder.lockCanvas();//清空画布
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);}catch (Exception e){e.printStackTrace();break;}//遍历弹幕集合
        for (int i = 0; i < Barrages.size(); i++) {mtext=Barrages.get(i);//如果弹幕类中的画笔为空,则在此处定义画笔,根据弹幕类中的颜色大小等进行绘制
            if (mtext.getPaint()==null){if (paint==null){paint=new Paint();}paint.setColor(mtext.getColor());paint.setTextSize(mtext.getSize());paint.setStrokeWidth(3f);}else {//如果弹幕类中的画笔不为空,则直接用弹幕类中的画笔绘制
                paint=mtext.getPaint();}//绘制文本
            canvas.drawText(mtext.getText(),mtext.getX(),mtext.getY(),paint);//如果弹幕超出屏幕左侧,则从集合中删除,否则进行移动
            if (mtext.getX()<-getWidth()){Barrages.remove(mtext);}else {mtext.setX((mtext.getX()-mtext.getSpeed()));}}//解锁画布
        surfaceHolder.unlockCanvasAndPost(canvas);try {Thread.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}}
}

大功告成,我们来看看如何调用,只需要执行msurfaceview.add方法添加弹幕即可。

public class MainActivity extends Activity {private mSurfaceView msurfaceView;private VideoView videoView;private Random random=new Random();private String[] strings={"6666","厉害了我的国","加油!!!","欢迎收看晨间新闻","程序猿很苦逼","我能怎么办,我也很无奈"};private int[] colors={Color.WHITE,Color.MAGENTA,Color.CYAN,Color.RED,Color.BLUE,Color.GREEN};@Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();}private void init() {msurfaceView = findViewById(R.id.msv);videoView = findViewById(R.id.mvv);//申请播放网络视频权限
        per();startVideo();//动态生成弹幕
        startBarrage();}//生成弹幕
    private void startBarrage() {new Thread(new Runnable() {@Override
            public void run() {while (true){mText mText=new mText();mText.setText(strings[random.nextInt(strings.length)]);mText.setSpeed(3);mText.setColor(colors[random.nextInt(colors.length)]);mText.setSize(40);msurfaceView.add(mText);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}//申请视频播放权限
    private void per() {if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {//检查是否有了权限
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {} else {//没有权限即动态申请
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);}}}//开始播放视频
    private void startVideo() {String url1 = "http://flashmedia.eastday.com/newdate/news/2016-11/shznews1125-19.mp4";Uri uri=Uri.parse(url1);//设置视频控制器
            videoView.setMediaController(new MediaController(this));//设置视频路径
            videoView.setVideoURI(uri);//开始播放视频
            videoView.start();}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context=".MainActivity"><VideoView
        android:id="@+id/mvv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        /><barrage.surfaceview.com.surfaceviewbarragedemo.mSurfaceView
        android:id="@+id/msv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" /></RelativeLayout>
github完整代码地址:安卓Android弹幕效果实现
PS:如有不正确的地方欢迎指出!

转载请注明:https://blog.csdn.net/weixin_41549915/article/details/80306476

安卓Android弹幕效果实现-简单易懂相关推荐

  1. android弹幕功能,很棒的Android弹幕效果实例

    很多项目需要用到弹幕效果,尤其是在播放视频的时候需要一起显示别人发的弹幕,也包括自己的发的. 今天就试着写了一下这个效果. 思路就是将从右往左的动画效果,字体内容,字体大小,弹幕平移速度等属性一起与T ...

  2. android 循环弹幕,Android弹幕效果

    上面效果图中白色的背景就是弹幕本身,是一个自定义的FrameLayout,我这里是为了更好的展示弹幕的位置才设置成了白色,当然如果是叠加在VideoView上的话,就需要设置成透明色了. 制作弹幕需要 ...

  3. 安卓Android事件总线EventBus简单使用

    EventBus是的主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息,优点是开销小,代码更优雅.以及将发送者和接收者 ...

  4. 安卓练习----安卓android实现一个石头剪刀布小游戏

    此博客用安卓android实现了一个简单的剪刀石头布小游戏.能完成人机对抗. 说明 这是我老师布置的一道课内作业,图片资源由老师提供,本篇博客仅展示代码部分,图片资源由于太多且没有那么必要,我就不在此 ...

  5. android 如何实现弹幕,Android简单实现弹幕效果

    本文实例为大家分享了Android实现弹幕效果的具体代码,供大家参考,具体内容如下 首先分析一下,他是由三层布局来共同完成的,第一层视频布局,第二层字幕布局,第三层输入框布局,要想让这三个布局在同一页 ...

  6. Android:简单的弹幕效果达到

    首先,效果图.分类似至360检测到的骚扰电话页面: 布局非常easy,上面是一个RelativeLayout,以下一个Button. 功能: (1)弹幕生成后自己主动从右側往左側滚动(Translat ...

  7. android 循环弹幕,Android自定义View实现弹幕效果

    原标题:Android自定义View实现弹幕效果 在很多视频直播中都有弹幕功能,而安卓上没有简单好用的弹幕控件,本文介绍一个自定义弹幕view的demo. 效果图: 思路: 自定义Textitem类表 ...

  8. Android弹幕功能实现,模仿斗鱼直播的弹幕效果,跪了

    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_ ...

  9. android实现弹幕功能,Android实现自定义的弹幕效果

    一.效果图 先来看看效果图吧~~ 二.实现原理方案 1.自定义ViewGroup-XCDanmuView,继承RelativeLayout来实现,当然也可以继承其他三大布局类哈 2.初始化若干个Tex ...

  10. Android弹幕功能实现,模仿斗鱼直播的弹幕效果

    转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/51933728 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭 ...

最新文章

  1. MyEclipse 中配置struts2.2.1的方法
  2. ohmyzsh用在mysql_oh-my-zsh,让你的终端从未这么爽过
  3. 打印合同_批量打印合同用印申请单
  4. 简单的WinInet编程
  5. C++语言之类class
  6. Windows Server2012虚拟内存设置
  7. keytool使用方法总结
  8. Memento 备忘录 快照模式 MD
  9. golang中的切片及内存拷贝
  10. ZOJ1222 Just the Facts【大数+模除】
  11. 巨头卡位新房赛道,与贝壳、易居相比,房多多的底牌是什么?
  12. 我对计算机的看法英语作文,我对创新的看法英语作文7篇作文
  13. html图片自动切换的幻灯片效果的,JS实现可切换图片的幻灯切换效果示例
  14. 阿里云服务器被恶意ddos攻击了怎么办?
  15. 自己想要什么 过什么样的生活
  16. vue所有页面刷新一次mounted(以及所有生命周期函数)执行两次的解决方法
  17. iphone html5音乐播放器,从界面到功能 五款iPhone音乐播放器年度横评
  18. crack与split的区别_Split or Crack? Split 和 Crack 两词的区别(
  19. Web 基础研发体系的建立
  20. comfort说明书 tp1200_西门子TP1200COMfort用什么编程软件

热门文章

  1. “圆球池塘”——动态交互作品
  2. 年底看机会,欢迎加入Java大数据招聘群!
  3. Linux创建一个有空间大小限制的目录提供给ftp用户
  4. 元宇宙、区块链和潘家园
  5. 什么是 JScript?
  6. infor wms 中英文对照_视听盛宴 I纸牌屋揭露美国政治权力运作(16中英、纯英、无字幕可切换视频+中英文全剧本+全季音频)...
  7. SOA、RPC/REST 和六边形架构
  8. 鉴源丨车载ECU嵌入式设备的诊断测试 - 会话和安全控制
  9. 租服务器的 直连100m是啥,如何知道我的服务器带宽是独享10M或者100M?
  10. 程序员的职业规划_程序员如何能做好职业规划,走出迷惘呢?这个能力矩阵法要告诉你...