iOS- 横向滚动跑马灯效果实现

833 阅读2分钟
原文链接: www.jianshu.com

一. demo效果如下:

二. 如何使用:

        下载github.com/moonCai/MNM…, 将MNMarqueeView拖入项目中初始化即可。在获取到文本标题后对MNMarqueeView对象的textList赋值,然后调用run(). 在需要暂停的合适地方调用pause(),在需要视图销毁时调用stop()。

三. 实现思路大纲:

    1.设置textLabelContainerView属性,作为文本控件(TextLabel)的容器视图;

    2.创建以下对象:

        TextLabel对象:展示newsTitle;

        onScreenTextLabels: [TextLabel]    记录屏幕上的TextLabel对象;

        offScreenTextLabels:[TextLabel]    记录离开textLabelContainerView的TextLabel对象(用于缓存离开屏幕的textLabel, 在下一个textLabel即将创建时使用。避免屏幕的内存开辟)。

    3. 设置displayLink属性,通过displayLink的定时源监听MNMarqueeView对象来实现横向滚动:

敲黑板,重点来了:

       通过速度 * displayLink的持续时长来获取偏移量。我在实现横向滚动这里的思路不是直接改变每个textLabel的偏移量。原因主要是:1.获取每个textLabel的“年龄”(自创建到当前时间的时长)较为繁琐。因此在这里借鉴系统组件UIScrollView的原理,改变容器视图的bounds从而改变其子视图的位置。

      因此,我在这里采取用定时源持续改变textLabelContainerView的bounds中x坐标的偏移量,textLabelContainerView的frame是没有被改变的。因此它在屏幕上的位置固定不变,添加在其上面的子视图持续偏移,这就是跑马灯实现的原理之一。

         第二个原理的着眼点在于如何给每个textLabel设置frame? 

         每个textLabel被创建出来就马上添加到onScreenTextLabels,直至它的maxX小于父视图的minX时就被移除,然后被添加到offScreenTextLabels。

         第一个被创建的textLabel,它的frame的x坐标是textLabelContainerView的bounds的l.frame.origin.x = textLabelContainerView.bounds.maxX。之后被创建的textLabel的frame.origin.x 被赋值为onScreenTextLabels最后一个元素的frame的maxX + 文本之间的间隔。

        此外,值得一说的是offScreenTextLabels。上文中有提及它起到的作用是复用。具体的原理是借鉴UITableView的复用机制。我在需要创建textLabel时,调用offScreenTextLabels的popLast()。也就是,如果最后一个元素存在就取出使用,offScreenTextLabels在取出后自动移除,如果最后一个元素不存在就新创建。

        最后要说的是一个细节处理:跑马灯左右两端的渐变模糊视图。显而易见,这么做的目的是为了柔和文本从移除父控件的视觉感受。渐变宽度和渐变色都留了接口,详情见demo中代码。