关于安卓自定义弹幕控件的实现(recyclerview)(一)

简介: 安卓自定义弹幕控件的实现(recyclerview)

!!!代码在文末!!!

背景

对于弹幕功能,稍微有点社交内容的app都会用到,其中,实现的方法有很多,本文主要通过
安卓原生recyclerview进行实现

思路

首先,recyclerview提供了api给开发者进行滚动的调用,同时也提供了相关接口,对滚动的
距离进行计算。因此,通过滑动距离监听,以及定时任务进行内容滚动,即可实现。

实现细节

对于上述思路以外,还要注意的是,recyclerview的滑动事件分发问题。本次需求要求的是
recyclerview不能与用户产生触摸交互,因此需要特别处理。
同时,需要注意对象引用问题。

实现过程

(一)定义好外部传入数据的方法
(二)定义一个定时器,用作定时滑动
(三)触摸距离计算,重新滚动逻辑设置
(四)处理触摸事件分发

实现说明

本次弹幕场景,仅仅是设置一次数据,若要进行分页加载,原理其实也是大同小异,稍作修改即可。

实现

(一)定义好一个setData方法,外部传入的是一个bean集合,集合的变量自行定义,这里我
定义的变量如下:

    //类型:1内容 2空布局填充
    private int type = 1;

    //昵称
    private String nickName;

    //文字
    private String content;

因为需求中,需要显示内容前,有一段空白的滑动距离,因此定义一个type==2的情况。

传入代码方法设置后,即可刷新adapter了,注意的是,每次刷新数据,都
需要对定时器进行cancel,否则会导致数据错乱的问题。
核心代码如下:

    /**
     * 设置数据
     */
    public void setData(List<BulletInfo> bulletList) {
        if (handler == null) {
            return;
        }
        if (System.currentTimeMillis() - mSetDataInterval < 1000) {
            return;
        }
        mSetDataInterval = System.currentTimeMillis();
        clearHandler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                //克隆数据
                List<BulletInfo> trainList = new ArrayList<>();
                if (bulletList == null || bulletList.size() == 0) {
                    trainList = new ArrayList<>();
                } else {
                    for (BulletInfo bulletInfo : bulletList) {
                        BulletInfo cache = new BulletInfo();
                        cache.setType(bulletInfo.getType());
                        cache.setContent(bulletInfo.getContent());
                        cache.setNickName(bulletInfo.getNickName());
                        trainList.add(cache);
                    }
                }
                mBulletCacheList.clear();
                mBulletCacheList.addAll(trainList);
                if (mInfoAdapter != null) {
                    mInfoAdapter.clear();
                    mInfoAdapter.setData(trainList);
                }
                scrollToPosition(0);
                startHandler();
            }
        });
    }

(二)定义定时器
这里使用Timer和TimerTask实现。通过查看源码发现,recyclerview的滑动方法,是支持子线程调用的,所以直接使用子线程执行的timer进行轮询。
核心代码如下:

    private void startHandler() {
        if (mTimer == null) {
            mTimer = new Timer();
        }
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    smoothScrollBy(0, 6);
                    //检查是否滑动到了底部
                    checkScrollToBottom();
                } catch (Exception e) {

                }
            }
        }, 10, 80);
    }

(三)触摸距离计算
触摸距离,本次实战中,其实用到了就是判断recyclerview是否滑动到底部的判断而已,没什么大不了的。主要的也是调用官方的api,直接放出核心代码:

    private void checkScrollToBottom() {
        //监听回调--------------------------------------------------
        try {
            //int offset, int progress, int duration, float percent
            //verticalOffset, verticalOffset + verticalExtent, verticalTotal,
            // (((verticalOffset + verticalExtent) * 1.0f) / (verticalTotal * 1.0f))
            int verticalExtent = computeVerticalScrollExtent();
            int verticalOffset = computeVerticalScrollOffset();
            int verticalTotal = computeVerticalScrollRange();
            float percent = (((verticalOffset + verticalExtent) * 1.0f) / (verticalTotal * 1.0f));
            if (percent == 1) {
                //已经到底了
                if (mInfoAdapter != null && mInfoAdapter.getData() != null &&
                        mInfoAdapter.getData().size() != 0) {
                    //重新设置数据
                    List<BulletInfo> trainResult = new ArrayList<>();
                    for (BulletInfo bulletInfo : mBulletCacheList) {
                        BulletInfo cache = new BulletInfo();
                        cache.setType(bulletInfo.getType());
                        cache.setContent(bulletInfo.getContent());
                        cache.setNickName(bulletInfo.getNickName());
                        trainResult.add(cache);
                    }
                    setData(trainResult);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

可以看到,主要方法有:

            int verticalExtent = computeVerticalScrollExtent();
            int verticalOffset = computeVerticalScrollOffset();
            int verticalTotal = computeVerticalScrollRange();

主要是计算recyclerview的滑动距离,范围,总距离,然后计算,即可得出滑动百分比。

(四)处理触摸事件
主要设置recyclerview不处理滑动事件即可,核心代码如下:


    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        return false;
    }

最后总结一下,若recyclerview在普通页面使用,直接调用设置数据方法即可,若在recyclerview中的子布局中使用,要注意recyclerview的复用问题,建议每次使用前,都把数据清空一次。

代码地址--库libbullet

that's all--------------------------------------------------------------------

目录
相关文章
|
2月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
47 2
基于Android P,自定义Android开机动画的方法
|
2月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
2月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
14天前
|
Android开发 开发者 索引
Android实战经验之如何使用DiffUtil提升RecyclerView的刷新性能
本文介绍如何使用 `DiffUtil` 实现 `RecyclerView` 数据集的高效更新,避免不必要的全局刷新,尤其适用于处理大量数据场景。通过定义 `DiffUtil.Callback`、计算差异并应用到适配器,可以显著提升性能。同时,文章还列举了常见错误及原因,帮助开发者避免陷阱。
34 9
|
15天前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
40 10
|
15天前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
39 8
|
20天前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
30 3
|
21天前
|
前端开发 Android开发 开发者
安卓应用开发中的自定义视图基础
【9月更文挑战第13天】在安卓开发的广阔天地中,自定义视图是一块神奇的画布,它允许开发者将想象力转化为用户界面的创新元素。本文将带你一探究竟,了解如何从零开始构建自定义视图,包括绘图基础、触摸事件处理,以及性能优化的实用技巧。无论你是想提升应用的视觉吸引力,还是追求更流畅的交互体验,这里都有你需要的金钥匙。
|
24天前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
2月前
|
XML 搜索推荐 Android开发
安卓开发中的自定义View组件实践
【8月更文挑战第30天】探索Android世界,自定义View是提升应用界面的关键。本文以简洁的语言带你了解如何创建自定义View,从基础到高级技巧,一步步打造个性化的UI组件。
下一篇
无影云桌面