6a645b0ce5bb939dabf7797cf9ba8aaa
SwiftUI - 如何创建一个强大的 Marquee(跑马灯)?

原文地址

许多 App 需要用到 Marquee(跑马灯)。在 UIKit 中我们可以使用
https://github.com/cbpowell/MarqueeLabel ,但是目前还没有成熟的 SwiftUI 库。

下面,让我们一起做一个强大的 Marquee

什么样的 Marquee 才是强大的?

  • 必须支持任意内容视图MarqueeLabel 只支持文本
  • 可以自定义动画的时长、自动回放、方向
  • 可以组合使用

Marquee 动画原理

Marquee 的原理是内容视图从 Marquee 的一端移动到另一端,然后一直循环

步骤

第一步要先获取 Marquee 和内容视图的宽度。关于这一点,你可以使用 GeometryReader and PreferenceKey 来实现。

GeometryReader 为我们提供了一个输入值,告诉我们可用的宽度和高度,然后我们可以将其用于需要的任何计算中。

struct ContentView: View {
    var body: some View {
        GeometryReader { geometry in
            Text("width: \(geometry.size.width)")
                .frame(width: geometry.size.width, height: 50)
                .background(Color.yellow)
        }
    }
}

众所周知,SwiftUI具有 environment 概念,可用于将数据向下传递到视图层次结构中。父视图与子视图共享其 environment 并订阅更改。但是有时我们需要将数据从子视图传递到父视图,这就是 PreferenceKey 发挥作用的地方。

```swift
struct ContentView: View {
@State var text: String = "\(Date())"
@State var textWidth: CGFloat = 0

var body: some View {
    GeometryReader { geometry in
        VStack {
            Text(text)
                .background(GeometryBackground())
                .background(Color.yellow)

            Text("text width: \(textWidth)")

            Button(action: {
                self.text = "\(Date())"
            }, label: {
                Text("change text")
            })
        }
    }
    // Listen content width changes
    .onPreferenceChange(WidthKey.self, perform: { value in
        self.textWidth = value
top Created with Sketch.