关于安卓自定义弹幕控件的实现(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--------------------------------------------------------------------

目录
相关文章
|
1月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
41 3
|
1月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
85 0
|
3月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
3月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
17天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
19天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
28 5
|
1月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
2月前
|
Android开发 开发者 索引
Android实战经验之如何使用DiffUtil提升RecyclerView的刷新性能
本文介绍如何使用 `DiffUtil` 实现 `RecyclerView` 数据集的高效更新,避免不必要的全局刷新,尤其适用于处理大量数据场景。通过定义 `DiffUtil.Callback`、计算差异并应用到适配器,可以显著提升性能。同时,文章还列举了常见错误及原因,帮助开发者避免陷阱。
191 9
|
2月前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
62 10
|
2月前
|
存储 缓存 Android开发
Android RecyclerView 缓存机制深度解析与面试题
本文首发于公众号“AntDream”,详细解析了 `RecyclerView` 的缓存机制,包括多级缓存的原理与流程,并提供了常见面试题及答案。通过本文,你将深入了解 `RecyclerView` 的高性能秘诀,提升列表和网格的开发技能。
70 8
下一篇
无影云桌面