9

I want to know if there's a way to enable horizontal scrolling of text i.e., marquee type text. I have used this library: https://github.com/cbpowell/MarqueeLabel and added the "MarqueeLabel.Swift" file to my application. But so far, it doesn't show the marquee effect that I wanted.

This is how I implemented it:

class ViewController: UIViewController 
{
@IBOutlet weak var marqueeLabel: MarqueeLabel! 
override func viewDidLoad() {
    super.viewDidLoad()
        self.marqueeLabel.tag = 101
        self.marqueeLabel.type = .Continuous
        self.marqueeLabel.speed = .Duration(5)
        self.marqueeLabel.animationCurve = .EaseInOut
        self.marqueeLabel.fadeLength = 10.0
        self.marqueeLabel.leadingBuffer = 30.0
        self.marqueeLabel.trailingBuffer = 20.0
        self.marqueeLabel.restartLabel()
 }
}

I have set the custom class in the interface builder according to the solution in MarqueeLabel Swift not working. It still doesn't work.

All I get is just a label displaying without the marquee effect (or horizontal text scroll).

P.S: I am new to iOS development too. Also, I tried using UIScrollView and UITextView before implementing this library. And I cannot use UIWebView as I'm trying to implement this in TVOS.

My questions are:

  1. Where did I go wrong with the code?

  2. Is there an alternative way to display marquee effect using Swift?

Thanks in advance.

Ruli
  • 2,592
  • 12
  • 30
  • 40
Swift
  • 397
  • 1
  • 2
  • 11
  • check this http://stackoverflow.com/a/33009837/5362916 – Uma Madhavi Feb 03 '16 at 08:53
  • 1
    @SwiftCake How long is the text string you're setting to the label? I ask because the scrolling animation only occurs if the text is long enough that it doesn't fit inside the label's frame size. Also calling `restartLabel()` shouldn't be necessary. – Chuck Feb 06 '16 at 17:01
  • @Chuck It's just 2-3 sentences long. Something like "This is a long text. This is a long text. This is a long text" But in TVOS if the sentence is long then it automatically scrolls. I want it to scroll using code and not automatically. – Swift Feb 08 '16 at 03:25
  • @SwiftCake the relatively-new tvOS demo in the MarqueeLabel-Swift repo does what I think you're wanting (the labels don't scroll until focused), by using the `holdScrolling` property. Check that out if you haven't already! – Chuck Feb 14 '16 at 19:08

7 Answers7

9

I used this little piece of code for my label to scroll like marquee:

@IBOutlet weak var firstLabel: UILabel! 
override func viewDidLoad() {
    super.viewDidLoad()

    UIView.animateWithDuration(12.0, delay: 1, options: ([.CurveLinear, .Repeat]), animations: {() -> Void in
            self.firstLabel.center = CGPointMake(0 - self.firstLabel.bounds.size.width / 2, self.firstLabel.center.y)
            }, completion:  { _ in })
}

Yes, it worked.

Swift
  • 397
  • 1
  • 2
  • 11
9

Updated for Swift 3 without using any third party library or pods

import UIKit

class ViewController: UIViewController {

    let redLabel: UILabel = {

        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = .boldSystemFont(ofSize: 16)
        label.textColor = .red
        label.text = "The first paragraph of the body should contain the strongest argument, most significant example, cleverest illustration, or an obvious beginning point."
        return label
    }()

    let greenLabel: UILabel = {

        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = .systemFont(ofSize: 14)
        label.textColor = .green
        label.text = "The second paragraph of the body should contain the second strongest argument, second most significant example, second cleverest illustration, or an obvious follow up the first paragraph in the body."
        return label
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "Marquee Label Demo"
        view.backgroundColor = .white

        view.addSubview(redLabel)
        view.addSubview(greenLabel)

        setupAutoLayout()
        startMarqueeLabelAnimation()
    }

    func startMarqueeLabelAnimation() {

        DispatchQueue.main.async(execute: {

            UIView.animate(withDuration: 10.0, delay: 1, options: ([.curveLinear, .repeat]), animations: {() -> Void in

                self.redLabel.center = CGPoint(x: 0 - self.redLabel.bounds.size.width / 2, y: self.redLabel.center.y)
                self.greenLabel.center = CGPoint(x: 0 - self.greenLabel.bounds.size.width / 2, y: self.greenLabel.center.y)

            }, completion:  nil)
        })
    }

    func setupAutoLayout() {

        redLabel.leftAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        redLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        redLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true

        greenLabel.leftAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        greenLabel.topAnchor.constraint(equalTo: redLabel.bottomAnchor, constant: 50).isActive = true
        greenLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
    }
}

Special Thanks:

https://stackoverflow.com/users/8303852/kartik-patel

https://stackoverflow.com/users/8388863/sid-patel

click here to see demo 1

iAj
  • 3,787
  • 1
  • 31
  • 34
  • How can I change the direction of text from RTL to LTR ? – Mohammad Mirzakhani Oct 19 '18 at 03:49
  • @MohammadMirzakhani you need to change the x value in centre & redLabel.rightAnchor instead of leftAnchor with the vice-versa... – iAj Oct 26 '18 at 03:42
  • thank you so mush for your answer, but I wrote below code and that code didn't work for me: self.marqueeLabel.center = CGPoint(x: self.marqueeLabel.center.x, y: self.marqueeLabel.center.y) – Mohammad Mirzakhani Oct 28 '18 at 12:52
6

Simple marquee - Swift 4.0:

override func viewDidLoad() {
    super.viewDidLoad()
    marqueeLabel.text = " text text here!"
    _ = Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(ViewController.marquee), userInfo: nil, repeats: true)
}
extension ViewController {
  @objc func marquee(){

    let str = marqueeLabel.text!
    let indexFirst = str.index(str.startIndex, offsetBy: 0)
    let indexSecond = str.index(str.startIndex, offsetBy: 1)
    marqueeLabel.text = String(str.suffix(from: indexSecond)) + String(str[indexFirst])

  }
}
Brian Bird
  • 1,176
  • 18
  • 21
3

In SWIFT 3:

@IBOutlet weak var YOURLABEL: UILabel!
override func viewDidLoad() {
    super.viewDidLoad()
    UIView.animate(withDuration: 12.0, delay: 1, options: ([.curveLinear, .repeat]), animations: {() -> Void in
        self.YOURLABEL.center = CGPoint(x: 0 - self.YOURLABEL.bounds.size.width / 2, y: self.YOURLABEL.center.y)
    }, completion:  { _ in })
}
pixelCss
  • 84
  • 1
  • 7
2

Since the original question was related to tvOS, I have just found out by mistake (after weeks of searching!) that tvOS 12 beta has implemented this:

enter image description here

One gets the marquee effect only when the ancestor is focused (like when we add a title to a movie poster and scroll to it), and sure, one may directly use TVPosterView from TVUIKit (like in this example) if that is the goal, but it works on single labels nonetheless.

Michele Dall'Agata
  • 1,474
  • 2
  • 15
  • 25
1

You should use like this then it will work.

NOTE: You can face performance issue by this because it's using recursion in Thread, so for better performance you should use with CATextLayer & CAScrollLayer.

import UIKit
import SnapKit

class ViewController: UIViewController {
    
    let label = UILabel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label.lineBreakMode = .byWordWrapping
        label.numberOfLines = 0
       
        label.text = "We couldn't turn around 'Til we were upside down I'll be the bad guy now But no, I ain't too proud I couldn't be there Even when I try You don't believe it We do this every time"
       
        view.addSubview(label)
        label.snp.makeConstraints { (make) in
           make.height.equalTo(20)
            make.top.leading.trailing.equalTo(self.view.safeAreaLayoutGuide).inset(50)
        }
      
        autoScroll()
    }
    
    @objc func autoScroll() {
        UIView.animate(withDuration: 12.0, delay: 1, options: ([.curveLinear, .repeat]), animations: {() -> Void in
            self.label.center = CGPoint(x: 0 - self.label.bounds.size.width / 2,y: self.label.center.y)
        }, completion:  { _ in
            self.autoScroll()
        })
    }
}
SomuYadav
  • 125
  • 6
0

In Swift 4

CODE

UIView.animate(withDuration: 1.0, delay: 1, options: ([.curveLinear, .repeat]), animations: {() -> Void in
            self.marqueeLABEL.center = CGPoint(x: self.marqueeLABEL.bounds.size.width, y: self.marqueeLABEL.center.y)
        }, completion:  { _ in })
Jitesh Prajapati
  • 2,533
  • 4
  • 29
  • 51
  • Doesn't marquee the label, just animates the view, the long text is not fully displayed too. – Arjun Jan 04 '20 at 12:56