Lui*_*uis 13 ios swift swiftui
如何从 Swift UI制作动画Text或TextField视图?
通过动画我的意思是,当文本更改时,它会“计数”。
例如,给定一些标签,如何创建动画,当我将标签文本设置为“100”时,它会从 0 上升到 100。我知道这在 UIKit 中使用图层和 CAAnimations 是可能的,但.animation()在 Swift UI 中使用该函数并且更改 a Textor的文本TextField在动画方面似乎没有任何作用。
我已经查看了Animatable协议及其相关animatableData属性,但它似乎Text既不TextField符合也不符合这一点。我正在尝试创建一个计数的标签,因此给定一些值,假设Double对该值的更改将被跟踪,要么使用@Stateor@Binding然后TextorTextField将根据值对其内容(实际字符串文本)进行动画处理达到它的设定。
编辑:
为了更清楚,我想重新创建一个动画时看起来像这样的标签:
kon*_*iki 19
在 SwiftUI 中有一种纯粹的动画文本方式。这是在 SwiftUI 中使用 AnimatableModifier 协议实现的进度指示器:
我写了一篇详尽的文章,记录了 AnimatableModifier(及其错误)的使用。它也包括进度指示器。你可以在这里阅读:https : //swiftui-lab.com/swiftui-animations-part3/
struct ContentView: View {
@State private var percent: CGFloat = 0
var body: some View {
VStack {
Spacer()
Color.clear.overlay(Indicator(pct: self.percent))
Spacer()
HStack(spacing: 10) {
MyButton(label: "0%", font: .headline) { withAnimation(.easeInOut(duration: 1.0)) { self.percent = 0 } }
MyButton(label: "27%", font: .headline) { withAnimation(.easeInOut(duration: 1.0)) { self.percent = 0.27 } }
MyButton(label: "100%", font: .headline) { withAnimation(.easeInOut(duration: 1.0)) { self.percent = 1.0 } }
}
}.navigationBarTitle("Example 10")
}
}
struct Indicator: View {
var pct: CGFloat
var body: some View {
return Circle()
.fill(LinearGradient(gradient: Gradient(colors: [.blue, .purple]), startPoint: .topLeading, endPoint: .bottomTrailing))
.frame(width: 150, height: 150)
.modifier(PercentageIndicator(pct: self.pct))
}
}
struct PercentageIndicator: AnimatableModifier {
var pct: CGFloat = 0
var animatableData: CGFloat {
get { pct }
set { pct = newValue }
}
func body(content: Content) -> some View {
content
.overlay(ArcShape(pct: pct).foregroundColor(.red))
.overlay(LabelView(pct: pct))
}
struct ArcShape: Shape {
let pct: CGFloat
func path(in rect: CGRect) -> Path {
var p = Path()
p.addArc(center: CGPoint(x: rect.width / 2.0, y:rect.height / 2.0),
radius: rect.height / 2.0 + 5.0,
startAngle: .degrees(0),
endAngle: .degrees(360.0 * Double(pct)), clockwise: false)
return p.strokedPath(.init(lineWidth: 10, dash: [6, 3], dashPhase: 10))
}
}
struct LabelView: View {
let pct: CGFloat
var body: some View {
Text("\(Int(pct * 100)) %")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(.white)
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用 aCADisplayLink中的 aBindableObject创建一个计时器,在动画期间更新文本。 要旨
class CADisplayLinkBinding: NSObject, BindableObject {
let didChange = PassthroughSubject<CADisplayLinkBinding, Never>()
private(set) var progress: Double = 0.0
private(set) var startTime: CFTimeInterval = 0.0
private(set) var duration: CFTimeInterval = 0.0
private(set) lazy var displayLink: CADisplayLink = {
let link = CADisplayLink(target: self, selector: #selector(tick))
link.add(to: .main, forMode: .common)
link.isPaused = true
return link
}()
func run(for duration: CFTimeInterval) {
let now = CACurrentMediaTime()
self.progress = 0.0
self.startTime = now
self.duration = duration
self.displayLink.isPaused = false
}
@objc private func tick() {
let elapsed = CACurrentMediaTime() - self.startTime
self.progress = min(1.0, elapsed / self.duration)
self.displayLink.isPaused = self.progress >= 1.0
self.didChange.send(self)
}
deinit {
self.displayLink.invalidate()
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用它:
@ObjectBinding var displayLink = CADisplayLinkBinding()
var body: some View {
Text("\(Int(self.displayLink.progress*100))")
.onAppear {
self.displayLink.run(for: 10.0)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6558 次 |
| 最近记录: |