Skip to content

Instantly share code, notes, and snippets.

@Chronos2500
Created May 13, 2025 15:19
Show Gist options
  • Save Chronos2500/688b2bb7fad02022c53d033d7e2517d5 to your computer and use it in GitHub Desktop.
Save Chronos2500/688b2bb7fad02022c53d033d7e2517d5 to your computer and use it in GitHub Desktop.
MarqueeLabel Please be fully aware that these use Private APIs.
let label = UILabel()
label.text = "Swift is a modern, intuitive programming language crafted for all Apple platforms."
label.setValue(true, forKey: "marqueeEnabled")
label.setValue(true, forKey: "marqueeRunning")
label.setValue(0, forKey: "marqueeRepeatCount")
//
// MarqueeLabel.swift
// PrivateAPISample
//
// Created by Chronos2500 on 2025/05/13.
//
import SwiftUI
fileprivate let text = """
Swift is a modern, intuitive programming language crafted for all Apple platforms.
"""
struct MarqueeLabelView: View {
var body: some View {
MarqueeLabel(
text,
font: .preferredFont(forTextStyle: .title1)
)
}
}
struct MarqueeLabel: UIViewRepresentable {
var text: String
var repeatCount: Int
var font: UIFont
var textColor: UIColor
init(
_ text: String,
repeatCount: Int = 0,
font: UIFont = .preferredFont(forTextStyle: .body),
textColor: UIColor = .label
) {
self.text = text
self.repeatCount = repeatCount
self.font = font
self.textColor = textColor
}
func makeUIView(context: Context) -> UILabel {
let label = UILabel()
label.text = text
label.textAlignment = .natural
label.font = font
label.textColor = textColor
label.backgroundColor = .clear
label.numberOfLines = 1
label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
label.setContentHuggingPriority(.defaultLow, for: .horizontal)
label.setContentHuggingPriority(.required, for: .vertical)
label.setContentCompressionResistancePriority(.required, for: .vertical)
label.adjustsFontForContentSizeCategory = true
label.setValue(true, forKey: "marqueeEnabled")
label.setValue(true, forKey: "marqueeRunning")
label.setValue(repeatCount, forKey: "marqueeRepeatCount")
label.setValue(40, forKey: "marqueeLoopPadding")
label.setValue(true, forKey: "marqueeUpdatable")
return label
}
func updateUIView(_ uiView: UILabel, context: Context) {
}
}
#Preview {
MarqueeLabelView()
}
@Chronos2500
Copy link
Author

Chronos2500 commented May 13, 2025

  • Setting marqueeRepeatCount to 0 will cause the marquee effect to repeat indefinitely. If a positive integer is specified, the marquee will stop after completing the specified number of repetitions.
  • By default, after completing one full scroll, the marquee pauses for a certain duration before repeating.
  • When the marquee effect is active, both ends of the content are automatically masked with a fading gradient effect.
  • By default, the marquee effect is not triggered if the content width is shorter than the view’s width.
MarqueeLabel.mov

@llsc12
Copy link

llsc12 commented May 17, 2025

Any way to make them pause to wait for another label to finish? Kinda like in apple music

@Chronos2500
Copy link
Author

Any way to make them pause to wait for another label to finish? Kinda like in apple music

@llsc12
To temporarily stop the marquee effect, execute setValue(false, forKey: "marqueeRunning").
In SwiftUI, it’s recommended to use a @ Binding variable and update the state within the updateUIView function.

@llsc12
Copy link

llsc12 commented May 17, 2025

@llsc12 To temporarily stop the marquee effect, execute setValue(false, forKey: "marqueeRunning"). In SwiftUI, it’s recommended to use a @ Binding variable and update the state within the updateUIView function.

@Chronos2500 how would i know when to stop one marquee label to wait for the other? presumably i'd need to know when the last label has finished before i can then tell all labels to run again right? thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment