如何在swift中创建一个简单的UILabel子类用于选框/滚动文本效果?

问题描述 投票:2回答:1

正如你在上面看到的那样,如果标签的文本太长,我试图编写UILabel的简单(!)子类来制作选框或滚动文本效果。我知道那里已经有很好的课程(例如https://cocoapods.org/pods/MarqueeLabel),但我想自己做:)

在下面你可以看到我目前的课程。我不能解决新标签向右滚动的问题,但也有第三个标签不应该存在。我认为这是标签本身。但是,当我尝试用该标签替换第一个附加标签时,我将无法工作。我希望它不会太混乱:/

对我来说很重要的是我只需要将故事板中的类分配给标签。因此,不需要去视图控制器(在插座旁边)添加代码。我希望很清楚我想要什么:D

再说一次:

  • UILabel的简单子类
  • 滚动标签
  • 应该在其他类中没有任何其他代码的情况下工作(例如,更改标签文本的插座除外,...)

(这是我自己的第一个子类,所以请随时教我如何正确:))

非常感谢你 !

到目前为止还不完美,但这是我目前的课程:

import UIKit

class LoopLabel: UILabel {

    var labelText : String?
    var rect0: CGRect!
    var rect1: CGRect!
    var labelArray = [UILabel]()
    var isStop = false
    var timeInterval: TimeInterval!
    let leadingBuffer = CGFloat(25.0)
    let loopStartDelay = 2.0

   required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.lineBreakMode = .byClipping
   }

    override var text: String? {
        didSet {
            labelText = text
            setup()
        }
    }

    func setup() {
        let label = UILabel()
        label.frame = CGRect.zero
        label.text = labelText

        timeInterval = TimeInterval((labelText?.characters.count)! / 5)
        let sizeOfText = label.sizeThatFits(CGSize.zero)
        let textIsTooLong = sizeOfText.width > frame.size.width ? true : false

        rect0 = CGRect(x: leadingBuffer, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
        rect1 = CGRect(x: rect0.origin.x + rect0.size.width, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
        label.frame = rect0

        super.clipsToBounds = true
        labelArray.append(label)
        self.addSubview(label)

        self.frame = CGRect(origin: self.frame.origin, size: CGSize(width: 0, height: 0))

        if textIsTooLong {
            let additionalLabel = UILabel(frame: rect1)
            additionalLabel.text = labelText
            self.addSubview(additionalLabel)

            labelArray.append(additionalLabel)

            animateLabelText()
        }
    }

    func animateLabelText() {
        if(!isStop) {
            let labelAtIndex0 = labelArray[0]
            let labelAtIndex1 = labelArray[1]

            UIView.animate(withDuration: timeInterval, delay: loopStartDelay, options: [.curveLinear], animations: {
                labelAtIndex0.frame = CGRect(x: -self.rect0.size.width,y: 0,width: self.rect0.size.width,height: self.rect0.size.height)
                labelAtIndex1.frame = CGRect(x: labelAtIndex0.frame.origin.x + labelAtIndex0.frame.size.width,y: 0,width: labelAtIndex1.frame.size.width,height: labelAtIndex1.frame.size.height)
            }, completion: { finishied in
                labelAtIndex0.frame = self.rect1
                labelAtIndex1.frame = self.rect0

                self.labelArray[0] = labelAtIndex1
                self.labelArray[1] = labelAtIndex0
                self.animateLabelText()
            })
        } else {
            self.layer.removeAllAnimations()
        }
    }
}
swift scroll uilabel subclass marquee
1个回答
2
投票

首先,如果您不需要在外部访问它们,我会保持变量私有,尤其是labelText(因为您正在使用要设置的计算属性文本)。

其次,由于您要将标签添加为子视图,我宁愿使用UIView作为容器而不是UILabel。故事板中唯一的区别是添加View而不是Label。

第三,如果使用此方法,则不应将(视图的)框架设置为零。

这样的事情会:

import UIKit

class LoopLabelView: UIView {

    private var labelText : String?
    private var rect0: CGRect!
    private var rect1: CGRect!
    private var labelArray = [UILabel]()
    private var isStop = false
    private var timeInterval: TimeInterval!
    private let leadingBuffer = CGFloat(25.0)
    private let loopStartDelay = 2.0

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    var text: String? {
        didSet {
            labelText = text
            setup()
        }
    }

    func setup() {
        self.backgroundColor = UIColor.yellow
        let label = UILabel()
        label.text = labelText
        label.frame = CGRect.zero

        timeInterval = TimeInterval((labelText?.characters.count)! / 5)
        let sizeOfText = label.sizeThatFits(CGSize.zero)
        let textIsTooLong = sizeOfText.width > frame.size.width ? true : false

        rect0 = CGRect(x: leadingBuffer, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
        rect1 = CGRect(x: rect0.origin.x + rect0.size.width, y: 0, width: sizeOfText.width, height: self.bounds.size.height)
        label.frame = rect0

        super.clipsToBounds = true
        labelArray.append(label)
        self.addSubview(label)

        //self.frame = CGRect(origin: self.frame.origin, size: CGSize(width: 0, height: 0))

        if textIsTooLong {
            let additionalLabel = UILabel(frame: rect1)
            additionalLabel.text = labelText
            self.addSubview(additionalLabel)

            labelArray.append(additionalLabel)

            animateLabelText()
        }
    }

    func animateLabelText() {
        if(!isStop) {
            let labelAtIndex0 = labelArray[0]
            let labelAtIndex1 = labelArray[1]

            UIView.animate(withDuration: timeInterval, delay: loopStartDelay, options: [.curveLinear], animations: {
                labelAtIndex0.frame = CGRect(x: -self.rect0.size.width,y: 0,width: self.rect0.size.width,height: self.rect0.size.height)
                labelAtIndex1.frame = CGRect(x: labelAtIndex0.frame.origin.x + labelAtIndex0.frame.size.width,y: 0,width: labelAtIndex1.frame.size.width,height: labelAtIndex1.frame.size.height)
            }, completion: { finishied in
                labelAtIndex0.frame = self.rect1
                labelAtIndex1.frame = self.rect0

                self.labelArray[0] = labelAtIndex1
                self.labelArray[1] = labelAtIndex0
                self.animateLabelText()
            })
        } else {
            self.layer.removeAllAnimations()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.