android开发分享Android Flutter实现弹幕效果

前言需求要点如下:弹幕行数为3行,每条弹幕相互依靠但不存在重叠每条弹幕可交互点击跳转滚动速度恒定 触摸不可暂停播放弹幕数据固定一百条且支持轮询播放弹幕排序规则如下:1 4 72 5 83 6 9通用弹

上述就是android开发分享Android Flutter实现弹幕效果的全部内容,如果对大家有所用处且需要了解更多关于Android学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

前言

需求要点如下:

  • 弹幕行数为3行,每条弹幕相互依靠但不存在重叠
  • 每条弹幕可交互点击跳转
  • 滚动速度恒定 触摸不可暂停播放
  • 弹幕数据固定一百条且支持轮询播放

弹幕排序规则如下:

1 4 7

2 5 8

3 6 9

通用弹幕实现方案

Android Flutter实现弹幕效果

flutter dev package已有开源弹幕实现组件,这里举例barrage_page的实现方式(大多数实现底层逻辑基本一样)。

基本架构采用stack然后向布局中提交弹幕布局,添加时设置好弹幕偏移量来设置弹幕位置。

stack(fit: stackfit.expand, children: <widget>[          widget.child,          _controller.isenabled              ? stack(              fit: stackfit.loose,              children: <widget>[]                ..addall(_widgets.values ?? const sizedbox()))              : const sizedbox(),        ]);      });  

弹幕效果代码

但因为每条弹幕可能会出现重叠情况无法合理定位每条弹幕的位置因此放弃该方案。

ps:widget只有在build到布局后才能获取到它基础信息(相对位置信息,宽高等)就无法计算出所有弹幕的位置信息。

listview弹幕方案实现

最先想到使用瀑布流flutter_staggered_grid_view实现弹幕布局但由于组件暂时不支持横向布局就放弃了。

基本框架

采用三个listview实现每一行弹幕效果。虽然不太推荐以这种形式实现但从快速实现效果来说是比较简单便捷兜底方案。(可以实现但不推荐)

container(    height: 200,    child: column(      children: [        expanded(          child: listview.builder(            scrolldirection: axis.horizontal,            controller: scrollcontroller1,            itembuilder: (context, index) {              return common.getwidget(index,                  height: 30, width: random.nextint(100).todouble());            },          ),        ),        expanded(            child: listview.builder(          scrolldirection: axis.horizontal,          controller: scrollcontroller2,          itembuilder: (context, index) {            return common.getwidget(index,                height: 30, width: random.nextint(100).todouble());          },        )),        expanded(            child: listview.builder(          scrolldirection: axis.horizontal,          controller: scrollcontroller3,          itembuilder: (context, index) {            return common.getwidget(index,                height: 30, width: random.nextint(100).todouble());          },        ))      ],    ),  )  

轮播滚动

添加定时器periodic定时每秒钟执行一次scrollcontrolleranimateto方法移动偏移量并且偏移量不断累加。

其次listview支持无限滑动只要listview.builder不设置itemcount就能实现。

timer _timer;    scroll = () {    offset += 100;    scrollcontroller1.animateto(offset,        duration: duration(seconds: 1), curve: curves.linear);    scrollcontroller2.animateto(offset,        duration: duration(seconds: 1), curve: curves.linear);    scrollcontroller3.animateto(offset,        duration: duration(seconds: 1), curve: curves.linear);  };  _timer = timer.periodic(duration(seconds: 1), (timer) {    scroll();  });  

轮询算法

listview支持无限滑动后itembuilder回调下标index会超出数据源最大值。因此数据源也需要支持无限轮询来配合列表滚动。start表示弹幕开始取值,这里设置为(0,1,2);index表示itembuilder回调下标index

int findindex(int start, int index) {    index = start + index * 3;    if (expresslist.length < index) {      index = index % (expresslist.length - 1); // 取余    } else if (expresslist.length == index) { // 是否是最后一个数据      index = start;      if (index >= expresslist.length) { // 还需要判断数据源是否比start还小        index = (index % expresslist.length - 1);      }    }    return index;  }  

点击事件

一切都实现得很顺利最终就是弹幕点击实现。但实际上当listviewscrollcontroller在执行animateto时其实点击操作是失效的,listview无法响应点击事件。只有当animateto操作结束之后再执行点击才能执行点击。因此若要实现这个功能只能先将timer暂停再执行一次点击,再一次点击不可能是用户再去触发,这里只能采用模拟点击形式实现。

ps:listview无法响应点击事件具体原因还待研究,个人猜测列表做动画时对外部触摸事件进行了屏蔽处理。

gesturedetector(    ontapup: (details){     // 点击抬起之后暂停定时器       _timer?.cancel();      // 模拟一次点击      timer(duration(milliseconds: 100),() {        gesturebinding.instance.handlepointerevent(pointeraddedevent(pointer: 0,position: details.globalposition));        gesturebinding.instance.handlepointerevent(pointerdownevent(pointer: 0,position: details.globalposition));        gesturebinding.instance.handlepointerevent(pointerupevent(pointer: 0,position: details.globalposition));      });    },    child: listview.builder(      controller: scrollcontroller,      physics: neverscrollablescrollphysics(),      itembuilder: (context, index) {        return gesturedetector(          behavior: hittestbehavior.opaque,          child: common.getwidget(index),          ontap: () {            // 内部响应点击事件 然后重新设置定时器滚动列表            _timer = timer.periodic(duration(seconds: 1), (timer) {              scroll();            });          },        );      },    ),  );  

Android&nbsp;Flutter实现弹幕效果

到此这篇关于android flutter实现弹幕效果的文章就介绍到这了,更多相关flutter弹幕效果内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/1108878.html

(0)
上一篇 2022年6月27日
下一篇 2022年6月27日

精彩推荐