本期将带领大家实现一个这样的效果,支持无限循环的单行弹幕效果。

实现思路分析

要实现上面的效果,我们先拆分下实现要素:

  • 1、弹幕布局是从屏幕的右侧向左侧滚动,单个弹幕之间的间距是固定的(设计要求)
  • 2、弹幕要支持无限滚动,出于性能要求,如果不在屏幕内的,应该移除,不能无限追加到内存里面。

拆分完需求要素之后,针对上面的需求要素,做一下思路解答:

  • 1、对于滚动和超出屏幕后移除,可以使用动画来实现,动画从屏幕右边开始移动到屏幕左边,监听如果已经动画结束,则remove掉布局。
  • 2、无限循环效果,可以使用两个链表实现,一个保存加入到屏幕的弹幕数据(A),另一个保存未添加到屏幕的弹幕数据(B)。让进入屏幕前将布局从B中poll出来,添加到A中。反之,屏幕移除的时候从A中poll出来,添加到B中。

代码实现

首先创建出来一个弹幕数据对象类

data class Danmu(//头像var headerUrl: String? = null,//昵称var userName: String? = null,//信息var info: String? = null,
)

要被使用的弹幕itemView

class DanmuItemView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayoutCompat(context, attrs, defStyleAttr) {private var danmuItemView: TextView? = nullvar danmu: Danmu? = nullinit {LayoutInflater.from(context).inflate(R.layout.danmu_item, this, true)danmuItemView = findViewById(R.id.tvDanmuItem)}fun setDanmuEntity(danmu: Danmu) {this.danmu = danmudanmuItemView?.text = "我是一个弹幕~~~~~哈哈哈哈哈哈" + danmu.userNamemeasure(0, 0)}
}

接下来就是弹幕布局的容器类,用来控制动画和数据交替。注意代码中有很有用的注释

class DanmuView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {private var mWidth = 0//为展示在屏幕上的弹幕数据private val mDanMuList = LinkedList<Danmu>()//屏幕中展示的弹幕数据private val mVisibleDanMuList = LinkedList<Danmu>()//判断是否在运行private val mIsRunning = AtomicBoolean(false)override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)mWidth = measuredWidth}/*** 添加弹幕数据*/fun enqueueDanMuList(danMuList: ArrayList<Danmu>) {danMuList.forEach {if (this.mDanMuList.contains(it).not()) {this.mDanMuList.add(it)}}if (mWidth == 0) {viewTreeObserver.addOnGlobalLayoutListener(object :ViewTreeObserver.OnGlobalLayoutListener {override fun onGlobalLayout() {mWidth = measuredWidthviewTreeObserver.removeOnGlobalLayoutListener(this)if (mIsRunning.get().not()) {mDanMuList.poll()?.apply {//这里是用来处理布局的交替工作,前面分析有说明mVisibleDanMuList.add(this)createDanMuItemView(this)}}}})} else {if (mIsRunning.get().not()) {mDanMuList.poll()?.apply {//这里是用来处理布局的交替工作,前面分析有说明mVisibleDanMuList.add(this)createDanMuItemView(this)}}}}private fun startDanMuAnimate(danMuItemView: DanmuItemView) {var isInit = falsedanMuItemView.animate()//注意这边设置的便宜量是容器布局的宽度+弹幕item布局的宽度,这样就确保滚动值刚好是从屏幕右侧外到屏幕左侧外.translationXBy((-(mWidth + danMuItemView.measuredWidth)).toFloat()).setDuration(6000).setInterpolator(LinearInterpolator()).setUpdateListener {val danMuTranslateX =(mWidth + danMuItemView.measuredWidth) * (it.animatedValue as Float)//这里是关键,用来确保每个item布局的间距一致,判断如果滚动进入屏幕的距离刚好是自身+20dp,也就是刚好空出来了20dp之后,紧接着下一个弹幕布局开始添加并动起来。if (danMuTranslateX >= danMuItemView.measuredWidth + Utils.convertDpToPixel(20F) && isInit.not()) {isInit = truemDanMuList.poll()?.apply {mVisibleDanMuList.add(this)createDanMuItemView(this)}}}.setListener(object : AnimatorListenerAdapter() {override fun onAnimationEnd(animation: Animator?) {if (mIsRunning.get().not()) {mIsRunning.set(true)}//很重要,在动画结束,也就是布局从屏幕移除之后,切记从布局中移除掉,//并且进行一波数据交替,方便实现无线循环danMuItemView.danmu?.let {mVisibleDanMuList.remove(it)mDanMuList.add(it)}removeView(danMuItemView)}}).start()}private fun createDanMuItemView(danMu: Danmu) {val danMuItemView = DanmuItemView(context).apply {setDanmuEntity(danMu)}//这里将布局添加之后,默认便宜到屏幕右侧出屏幕,造成布局总是从右												

实现一个横向无限循环滚动的单行弹幕效果相关推荐

  1. 在线直播系统源码,横向无限循环滚动的单行弹幕效果

    在线直播系统源码,横向无限循环滚动的单行弹幕效果实现的相关代码 实现思路分析 要实现上面的效果,我们先拆分下实现要素: 1.弹幕布局是从屏幕的右侧向左侧滚动,单个弹幕之间的间距是固定的(设计要求) 2 ...

  2. 【Android】ViewPager实现无限循环滚动

    最近做的一个项目,客户要求在ViewPager实现的主页面中滑动到最后一页后继续滑动能返回到第一页,也就是实现无限循环滚动,效果如下: 看了下ViewPager没有滑到尽头的回调方法,因此想到的解决方 ...

  3. Swiper:无限循环滚动时出现空白页/页面内容不刷新

    问题描述 使用Swiper插件实现列表的无限循环滚动效果,记录遭遇的两个问题:①滚动到某页时界面显示空白:②用id唯一标识列表中需要动态改变的值,在改变某一id的div内容后,页面显示内容并未改变 问 ...

  4. ios之实现自动无限循环滚动视图(1)

    ios之实现自动无限循环滚动视图(1) 前言 效果展示 功能 分析 全部代码 前言 ios实现无限循环滚动主要有两种办法,都利用了UIScrollView,第一种是创建一个很大的UIScrollVie ...

  5. unity实现图片轮播效果_unity 背景无限循环滚动效果

    背景无限循环滚动效果如下示: 步骤如下: 导入背景图片后,设置图片的格式,如下图: 2.图片格式也可以设置是Texture格式,但是Wrap Mode 一定要是Repeat[重复发生]:然后记得App ...

  6. Unity的ScrollView无限循环滚动

    前言 此篇文章当作知识学习即可,需要使用循环复用的小伙伴可以尝试博主近期开发的ScrollCircleMaker v1.0,此插件功能比较完整,使用方便,如果遇到问题可以联系我进行修改. 当Scrol ...

  7. Unity3d学习笔记-无限循环滚动背景(完整的商店广告牌组件)

    在游戏项目中我们常常看到商城的广告牌,几张广告图片循环滚动,类似跑马灯,现在我将讨论一种实现方法,并提供一个管理类,大家可以直接使用. 实现原理:背景图片循环滚动的原理很简单:两张图片向一个方向移动, ...

  8. JQuery图片无限循环滚动源码

    平常项目中经常用到图片循环滚动,所以就写些必要的CSS定位,JS基本算法,最后就封装成JQuery图片无限循环滚动插件类,其实本质上是li块无限循环滚动,li块里面不管是图片还是其它内容,都OK的. ...

  9. [jQuery基础] jQuery动效案例(二) -- 图标特效、无限循环滚动(简易轮播图)

    图标特效 实现效果展示 实现步骤 第一步(实现静态效果) CSS部分 *{margin: 0;padding: 0; } ul{list-style: none;width: 400px;height ...

最新文章

  1. freeyellowe—book_剑桥少儿英语yellow book内容
  2. 神经网络优化中的Weight Averaging
  3. 程序员必备:提升开发效率神器,强烈推荐 !!!
  4. Machine Learning - Coursera week6 Evaluating a learning algorithm
  5. python中关于深拷贝和浅拷贝的详解
  6. hadoop--MapReduce_WordCount词频统计案例
  7. 保存blob到本地_用12行代码提取浏览器自动保存的密码
  8. ByteBufferMessageSet分析
  9. java.util.concurrent.RejectedExecutionException: event executor terminated 错误分析
  10. 织梦php版本图片不能上传,织梦Dedecms会员中心无法上传图片的解决方法
  11. UI设计师SVG动画进阶篇——路径变形动画(上篇)
  12. 第二十五章 合作博弈论【相关策略与相关均衡】
  13. python游戏设计毕业论文_游戏毕业设计论文
  14. php语言的cmpp协议应用
  15. Linux——进程间通信(管道)
  16. 数字化转型建设的基本模型与能力构建
  17. python PNG图片显示
  18. c语言中isupper用法,C语言 isupper()用法及代码示例
  19. IT管理到底是做什么
  20. android 侧滑删除方法,Android 基于RecyclerView的Item侧滑删除

热门文章

  1. 两种方式构建vue单页面多组件应用
  2. Linux 上面一些操作:解压,压缩带密码,屏幕录制
  3. Openshift Origin开发日记 1 - 10
  4. 软件工程期末考试速成(考试题)
  5. 都在谈人工智能,但你知道它的潜力、实践意义、障碍是什么吗?
  6. CoreOS实践指南(三):系统服务管家Systemd
  7. Appstore app链接mt参数app类型解析
  8. [CVPR-20] Randaugment: Practical automated data augmentation with a reduced search space
  9. 超简单利用java实现猜数字大小游戏2
  10. 为什么这么多人用代理IP,使用代理IP的效果怎么样