当前位置: 首页 > article >正文

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

引言

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

本篇博客将介绍如何使用  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.kler.cn/a/538991.html

相关文章:

  • 【Matlab优化算法-第13期】基于多目标优化算法的水库流量调度
  • DeepSeek 评价开源框架存在幻觉么?
  • 【玩转 Postman 接口测试与开发2_019】第15章:利用 Postman 初探 API 性能测试(含实战截图)
  • 【Spring】什么是Spring?
  • RabbitMQ 从入门到精通:从工作模式到集群部署实战(四)
  • OpenCV:图像修复
  • CF998A Balloons​ 构造 ​
  • 牛客寒假集训营1
  • 基于Java的远程视频会议系统(源码+系统+论文)
  • 数据库如何清空重置索引,MySQL PostgreSQL SQLite SQL Server
  • ToDesk云电脑将终结显卡溢价,Web端浏览器、安卓、IOS免费试用
  • 【C++学习篇】C++11
  • Mac电脑修改hosts文件内容
  • 高效知识管理与分类优化指南:从目录设计到实践应用
  • SSA-TCN麻雀算法优化时间卷积神经网络时间序列预测未来Matlab实现
  • 力扣-字符串-28 找出字符串中第一个匹配项的下标
  • PyTorch Profiler 的使用
  • 2024年个人总结:求变
  • 自动化测试工具:selenium
  • mysql8 用C++源码角度看客户端发起sql网络请求,并处理sql命令
  • Spring Boot整合DeepSeek实现AI对话
  • TensorFlow 示例平方米转亩(二)
  • e2studio开发RA4M2(11)----AGT定时器频率与占空比的设置
  • Vue(7)
  • 单元测试的入门实践与应用
  • java-异常家族梳理(流程图)