iOS 自动翻滚广告条(榜单条)实现方案

news2025/2/11 4:43:13

引言

在直播场景中,榜单信息、活动公告或者广告推广通常需要以醒目的方式展示,但由于屏幕空间有限,一次只能显示一条内容。为了让用户能够持续关注这些信息,我们可以实现一个自动翻滚的广告条(或榜单条),让内容定期滚动更新,类似于上下轮播的效果。

本篇博客将介绍如何使用  UITableView + Timer 来实现这一功能,使其能够自动滚动循环播放,并且在数据更新时依然保持流畅的用户体验。

代码实现

我们以直播间的小时榜信息条为例。由于该场景下的数据更新频率较低,并且滚动不需要过快,而是以固定速度自动翻滚,因此采用UITableView + Timer的方案即可满足需求。

在定时器的选择上,我们使用了Repeat,相比于手动管理Timer的启动和销毁,这种方式更加简洁高效,能够稳定地控制翻滚节奏。

基本UI结构

翻滚条的全部UI就是一个UITableView,但记得设置它不可交互放置用户手动滚动。

class MWVerticalAutoRollView: UIView,UITableViewDelegate,UITableViewDataSource {
    
    /// 滚动列表视图
    private let tableView = UITableView(frame: .zero,style: .plain)
    ....
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        addTableView()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 添加列表
    private func addTableView() {
        self.addSubview(tableView)
        tableView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        tableView.backgroundColor = .clear
        tableView.isPagingEnabled = true
        tableView.isScrollEnabled = false
        tableView.delegate = self
        tableView.dataSource = self
        tableView.separatorStyle = .none
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
    }
    
    /// 注册cell 泛型
    /// - Parameter
    func registerCell<T:UITableViewCell>(cell:T.Type) {
        tableView.register(cell, forCellReuseIdentifier: NSStringFromClass(cell))
    }
  1. 创建UITableView的实例,当做上下翻滚的列表。
  2. 设置UITableView的布局,分页,以及禁止滑动事件。
  3. 此外创建了一个对外暴漏的方法用来注册自定义UITableViewCell。

数据处理

想要实现无限的翻滚,以及针对只有一条数据的情况我们首先需要给数据进行处理,主要将第一个数据再次添加到最后一个数据,和轮播一样,以实现假的无限翻滚。

    /// 数据模型数组
    private var dataList:[Any] = []
    /// 设置数据
    /// - Parameter dataList: 数据
    func setData(dataList:[Any]) {
        var results:[Any] = []
        if dataList.count == 0 {
            return
        }
        if dataList.count == 1 {
            results.append(dataList.first!)
            results.append(dataList.first!)
            results.append(dataList.first!)
        }
        if dataList.count == 2 {
            results.append(dataList.first!)
            results.append(dataList.last!)
            results.append(dataList.first!)
        }
        if dataList.count >= 3 {
            results = dataList
            results.append(dataList.first!)
        }
        self.dataList = results
        tableView.reloadData()
        startTimer()
    }

在UITableView的代理方法中,显示dataList数据。

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataList.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let delegate = delegate {
            let data = dataList[indexPath.row]
            return delegate.mwVerticalAutoRollView(self, cellForRowAt: indexPath, data: data)
        }
        MWAssert(false, "MWVerticalAutoRollView delegate is nil!")
        return tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    }
    
    func dequeueReusableCell<T:UITableViewCell>(cell:T.Type,indexPath:IndexPath) -> T {
        return tableView.dequeueReusableCell(withIdentifier: NSStringFromClass(cell), for: indexPath) as! T
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 24.0
    }
  1. 数据的数量直接使用dataList.count放回。
  2. UITableView的cell,我们通过代理向该组件内部传递,这样我们可以自定义任何样式的滚动item。
  3. 固定列表高度为24。

实现定时滚动

使用Repeater每2.5秒执行一次,每次切换到下一个row,当切换到最后一个时,隐藏动画直接切换到第一个以实现无线翻滚。

    private func startTimer() {
        self.timer = Repeater.every(.seconds(2.5)) { [weak self] _ in
            guard let self = self else { return }
            DispatchQueue.main.async {
                self.autoScroll()
            }
        }
    }
    
    @objc func autoScroll() {
        currentIndex += 1
        if currentIndex >= dataList.count {
            currentIndex = 0
            // 无动画跳回开头
            CATransaction.begin()
            CATransaction.setDisableActions(true)
            tableView.scrollToRow(at: IndexPath(row: currentIndex, section: 0), at: .top, animated: false)
            CATransaction.commit()
        } else {
            // 平滑滚动到下一行
            tableView.scrollToRow(at: IndexPath(row: currentIndex, section: 0), at: .top, animated: true)
        }
    }
  1. 开始定时器,主线程执行滚动方法。
  2. 每次执行autoScroll()方法,currentIndex+1,滚动到下一行。
  3. 如果已经是最后一行,将currentIndex设置为0,隐藏隐式动画,无动画切换到第一行。

使用示例

组件使用起来非常简单,在需要使用的地方直接创建广播滚动组件MWVerticalAutoRollView的实例,并设置对应布局和数据。

    /// 滚动榜单视图
    private let rollHotListView = MWVerticalAutoRollView()
    
    /// 榜单数据列表
    private var rollHotListDataList = [String]()
    /// 添加滚动榜单视图
    private func addRollHotListView() {
        guard let containerView = self.horSliderContentView else {
            return
        }
        containerView.addSubview(rollHotListView)
        rollHotListView.isHidden = true
        rollHotListView.delegate = self
        rollHotListView.snp.makeConstraints { (make) in
            make.leading.equalToSuperview().offset(16.0)
            make.top.equalToSuperview().offset(MW_TOP_SAFE_HEIGHT + 72)
            make.height.equalTo(24.0)
            make.trailing.equalToSuperview().offset(-16.0)
        }
        rollHotListView.registerCell(cell: MWRollHotListCell.self)
    }

        rollHotListView.setData(dataList: dataList)

实现代理方法,在代理方法中为自定义的WMRollHotListcell渲染数据。

    func mwVerticalAutoRollView(_ view: MWVerticalAutoRollView, cellForRowAt indexPath: IndexPath,data:Any) -> UITableViewCell {
        let cell = view.dequeueReusableCell(cell: MWRollHotListCell.self, indexPath: indexPath)
        if let content = data as? MWRollHotListModel {
            cell.rollHotListModel = content
        }
        cell.selectionStyle = .none
        cell.backgroundColor = .clear
        cell.contentView.backgroundColor = .clear
        return cell
    }

结语

通过使用 UITableView + Timer 实现自动翻滚的广告条或榜单条,我们能够在直播间等场景中,简便且高效地展示动态信息。这个方案既满足了平滑滚动的需求,又避免了频繁的数据更新带来的性能问题。同时,通过简单的定时器控制,我们能够灵活地调整滚动的速度和频率,保证了良好的用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2295467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉-拟合

一、拟合 拟合的作用主要是给物体有一个更好的描述 根据任务选择对应的方法&#xff08;最小二乘&#xff0c;全最小二乘&#xff0c;鲁棒最小二乘&#xff0c;RANSAC&#xff09; 边缘提取只能告诉边&#xff0c;但是给不出来数学描述&#xff08;应该告诉这个点线是谁的&a…

【JVM详解一】类加载过程与内存区域划分

一、简介 1.1 概述 JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关…

Unity项目接入xLua的一种流程

1. 导入xlua 首先导入xlua&#xff0c;这个不用多说 2. 编写C#和Lua交互脚本 基础版本&#xff0c;即xlua自带的版本 using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System; using System.IO;[Serializable] public…

Deepseek 接入Word处理对话框(隐藏密钥)

硅基流动邀请码&#xff1a;1zNe93Cp 邀请链接&#xff1a;网页链接 亲测deepseek接入word&#xff0c;自由调用对话&#xff0c;看截图有兴趣的复用代码&#xff08;当然也可以自己向deepseek提问&#xff0c;帮助你完成接入&#xff0c;但是提问逻辑不一样给出的答案是千差万…

Office/WPS接入DS等多个AI工具,开启办公新模式!

在现代职场中&#xff0c;Office办公套件已成为工作和学习的必备工具&#xff0c;其功能强大但复杂&#xff0c;熟练掌握需要系统的学习。为了简化操作&#xff0c;使每个人都能轻松使用各种功能&#xff0c;市场上涌现出各类办公插件。这些插件不仅提升了用户体验&#xff0c;…

ximalaya(三) playUriList值解密--webpack

本文主要介绍解密音频播放url参数。 本文仅代表个人理解&#xff0c;如有其他建议可在评论区沟通。 声明 仅仅记录一下自己的学习方法&#xff0c;不作为其他参考、更不作为商业用途。如有侵犯请联系本人删除 目标地址&#xff1a;aHR0cHM6Ly93d3cueGltYWxheWEuY29tL3NvdW5k…

ASP.NET Core JWT

目录 Session的缺点 JWT&#xff08;Json Web Token&#xff09; 优点&#xff1a; 登录流程 JWT的基本使用 生成JWT 解码JWT 用JwtSecurityTokenHandler对JWT解码 注意 Session的缺点 对于分布式集群环境&#xff0c;Session数据保存在服务器内存中就不合适了&#…

光伏-报告显示,假期内,硅料端签单顺序发货相对稳定。若3月份下游存提产,则不排除硅料价格有上调预期。

据TrendForce集邦咨询报告显示&#xff0c;假期内&#xff0c;硅料端按照前期签单顺序发货&#xff0c;相对稳定。若3月份下游存提产&#xff0c;则不排除硅料价格有上调预期。 002306中科云网 旅游 | 公司为提供复合菜系特色餐饮的连锁企业&#xff0c;形成了以粤菜&#xff…

【信息系统项目管理师-案例真题】2017上半年案例分析答案和详解

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 试题一【问题1】8 分【问题2】4 分【问题3】8 分【问题4】5 分试题二【问题1】10 分【问题2】8 分【问题3】6 分【问题4】5 分试题三【问题1】5 分【问题2】7 分【问题3】6 分【问题4】3 分试题一 阅读下列说明…

滴水逆向_程序实现弹窗修改OEP

作业&#xff1a; 几个很重要的注意事项。 1 我们模拟的是内核如何将一个文件硬盘中拉伸到内存中&#xff0c;但是我们做的仅仅是 模拟拉伸过程。也就是说其中的属性字段是无差别的拷贝的。 但是加载exe的时候 &#xff0c;imagebase 是随机分配的。 我们打开内存中的exe&…

快速上手——.net封装使用DeekSeek-V3 模型

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,用爱发电,去丈量人心,是否能达到人机合一?开工大吉 新的一年就这么水灵灵的开始了,在这里,祝各位读者新春快乐,万事如意! 新年伊…

ReactNative进阶(五十九):存量 react-native 项目适配 HarmonyOS NEXT

文章目录 一、前言二、ohos_react_native2.1 Fabric2.2 TurboModule2.2.1 ArkTSTurboModule2.2.2 cxxTurboModule&#xff1a; 三、拓展阅读 一、前言 2024年10月22日19:00&#xff0c;华为在深圳举办“原生鸿蒙之夜暨华为全场景新品发布会”&#xff0c;主题为“星河璀璨&…

1-2 面向对象编程方法

1.0 面向对象编程思维 在面向对象风格中&#xff0c;结构体被看做数据&#xff08;data&#xff09;&#xff0c;而操作数据的函数称作方法&#xff08;method&#xff09;。目前函数 和数据是分离的&#xff0c;函数并不直接操作数据&#xff0c;我们需要拿到函数返回的结果&a…

CSS 组合选择符详解与实战示例

在 Web 开发过程中&#xff0c;CSS 用于定义页面元素的样式&#xff0c;而选择器则帮助我们精确定位需要添加样式的元素。今天我们主要来讲解 CSS 中的组合选择符&#xff0c;它们能够根据 DOM 结构中元素之间的关系来选中目标元素&#xff0c;从而写出结构清晰、易于维护的 CS…

html为<td>添加标注文本

样式说明&#xff1a; /*为td添加相对定位点*/ .td_text {position: relative; }/*为p添加绝对坐标(相对于父元素中的定位点)*/ .td_text p {position: absolute;top: 80%;font-size: 8px; }参考资料&#xff1a;

apachePoi中XSSFClientAnchor图片坐标简述;填充多张图片

概述 业务中经常会遇到在单元格内填充图片的需求&#xff0c;而且要求指定图片在单元格内的位置。 一般都是用的apache的poi&#xff0c;设置图片坐标。 HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)dx1 dy1 起始单元…

无界构建微前端?NO!NO!NO!多系统融合思路!

文章目录 微前端理解1、微前端概念2、微前端特性3、微前端方案a、iframeb、qiankun --> 使用比较复杂 --> 自己写对vite的插件c、micro-app --> 京东开发 --> 对vite支持更拉跨d、EMP 方案--> 必须使用 webpack5 --> 很多人感觉不是微前端 --> 去中心化方…

为飞牛OS基于FRP的内网穿透开启HTTPS加密

前言 玩NAS的朋友应该有比较多只是在家庭局域网使用&#xff0c;比如日常看看电影、备份手机照片什么的&#xff0c;这属于家庭局域网的使用场景。 当然了&#xff0c;如果你经常出差&#xff0c;或者过年回家不想把NAS也背回去&#xff0c;或者是想上班摸鱼&#xff0c;或者是…

《基于Python与DashScope的智能语音合成工具开发》

《基于Python与DashScope的智能语音合成工具开发》 在当今数字化时代&#xff0c;语音合成技术已经广泛应用于各种场景&#xff0c;如智能语音助手、有声读物、导航系统等。本文将介绍如何使用Python和DashScope平台开发一个简单而功能强大的文字转语音工具。通过这个工具&…

快速上手Vim的使用

Vim Linux编辑器-vim使用命令行模式下所有选项都可以带数字底行模式可视块模式&#xff08;ctrlV进入&#xff09; Linux编辑器-vim使用 Vim有多种模式的编辑器。能帮助我们很快的进行代码的编辑&#xff0c;甚至完成很多其他事情。 默认情况下我们打开vim在命令模式下&#x…