當我遇到一個奇怪的問題時,我正在 SwiftUI 中處理一個有趣的影片,該問題涉及對 SwiftUI 的 SF 符號進行影片更改。基本上,我想為一組不斷擴大的圓圈設定影片,這些圓圈隨著距離越來越遠而失去不透明度。當我使用Circle()形狀為圓圈設定影片時,這很好用,但是當我使用Image(systemName: "circle"). 也就是說,它拋出No symbol named 'circle' found in system symbol set并且我在 Xcode 中遇到了可怕的“紫色”錯誤。為什么我的影片適用于形狀而不適用于 SF 符號?
帶形狀的影片代碼:
struct ContentView: View {
let timer = Timer.publish(every: 0.25, on: .main, in: .common).autoconnect()
@State var firstIndex: Int = 0
@State var secondIndex: Int = 10
@State var thirdIndex: Int = 20
@State var fourthIndex: Int = 30
private func changeIndex(index: Int) -> Int {
if index == 40 {
return 0
} else {
return index 1
}
}
var body: some View {
ZStack {
Circle()
.foregroundColor(.black)
.frame(width: 10, height: 10)
ExpandingCircle(index: firstIndex)
ExpandingCircle(index: secondIndex)
ExpandingCircle(index: thirdIndex)
ExpandingCircle(index: fourthIndex)
}
.onReceive(timer) { time in
withAnimation(.linear(duration: 0.25)) {
self.firstIndex = changeIndex(index: firstIndex)
self.secondIndex = changeIndex(index: secondIndex)
self.thirdIndex = changeIndex(index: thirdIndex)
self.fourthIndex = changeIndex(index: fourthIndex)
}
}
}
}
其中ExpandingCircle定義為:
struct ExpandingCircle: View {
let index: Int
private func getSize() -> CGFloat {
return CGFloat(index * 2)
}
private func getOpacity() -> CGFloat {
if index == 0 || index == 40 {
return 0
} else {
return CGFloat(1 - (Double(index) * 0.025))
}
}
var body: some View {
Circle()
.strokeBorder(Color.red, lineWidth: 4)
.frame(width: getSize(), height: getSize())
.opacity(getOpacity())
}
}
復制錯誤,換出ExpandingCircle在ContentView用于ExpandingCircleImage:
struct ExpandingCircleImage: View {
let index: Int
private func getSize() -> CGFloat {
return CGFloat(index * 2)
}
private func getOpacity() -> CGFloat {
if index == 0 || index == 40 {
return 0
} else {
return CGFloat(1 - (Double(index) * 0.025))
}
}
var body: some View {
Image(systemName: "circle")
.foregroundColor(.red)
.font(.system(size: getSize()))
.opacity(getOpacity())
}
}
uj5u.com熱心網友回復:
您ExpandingCircleImage正在窒息,因為您不能擁有大小為 0 的系統字體,并且您一直試圖將 0 輸入到您的ExpandingCircleImage視圖中。但是,除此之外,您不需要使用計時器來驅動影片。事實上,它使影片看起來很奇怪,因為計時器不準確。接下來,您的ExpandingCircle或ExpandingCircleImage應該影片自己并成為完整的效果。
當您修復字體大小 = 0 問題時,您將遇到的下一個問題是它.font(.system(size:))不能按原樣設定影片。你需要AnimatableModifier為它寫一個。看起來像這樣:
struct AnimatableSfSymbolFontModifier: AnimatableModifier {
var size: CGFloat
var animatableData: CGFloat {
get { size }
set { size = newValue }
}
func body(content: Content) -> some View {
content
.font(.system(size: size))
}
}
extension View {
func animateSfSymbol(size: CGFloat) -> some View {
self.modifier(AnimatableSfSymbolFontModifier(size: size))
}
}
該animatableData變數是關鍵。它教 SwiftUI 改變什么來渲染影片。在這種情況下,我們正在為字體的大小設定影片。視圖擴展只是一種方便,因此我們可以使用.符號。
為這樣的視圖設定影片的另一個技巧是使用多個影片,這些影片只占整體的一部分。換句話說,如果你用四個圓圈,第一個是 25%,接下來是 25% 到 50%,然后是 50% 到 75%,最后是 75% 到 100%。你似乎也希望環隨著擴展而褪色,所以我也寫了。下面的代碼將有兩個影片視圖,一個用形狀制作,一個用 SF 符號。
struct ContentView: View {
var body: some View {
VStack {
Spacer()
ZStack {
Circle()
.foregroundColor(.black)
.frame(width: 10, height: 10)
ExpandingCircle(maxSize: 100)
}
.frame(height: 100)
Spacer()
ZStack {
Circle()
.foregroundColor(.black)
.frame(width: 10, height: 10)
ExpandingCircleImage(maxSize: 100)
}
.frame(height: 100)
Spacer()
}
}
}
struct ExpandingCircle: View {
let maxSize: CGFloat
@State private var animate = false
var body: some View {
ZStack {
Circle()
.strokeBorder(Color.red, lineWidth: 8)
.opacity(animate ? 0.75 : 1)
.scaleEffect(animate ? 0.25 : 0)
Circle()
.strokeBorder(Color.red, lineWidth: 8)
.opacity(animate ? 0.5 : 0.75)
.scaleEffect(animate ? 0.5 : 0.25)
Circle()
.strokeBorder(Color.red, lineWidth: 8)
.opacity(animate ? 0.25 : 0.5)
.scaleEffect(animate ? 0.75 : 0.5)
Circle()
.strokeBorder(Color.red, lineWidth: 8)
.opacity(animate ? 0 : 0.25)
.scaleEffect(animate ? 1 : 0.75)
}
.frame(width: maxSize, height: maxSize)
.onAppear {
withAnimation(.linear(duration: 4).repeatForever(autoreverses: false)) {
animate = true
}
}
}
}
struct ExpandingCircleImage: View {
let maxSize: CGFloat
@State private var animate = false
var body: some View {
ZStack {
Image(systemName: "circle")
.animateSfSymbol(size: animate ? (maxSize * 0.25) : 1)
.opacity(animate ? 0.75 : 1)
Image(systemName: "circle")
.animateSfSymbol(size: animate ? (maxSize * 0.5) : (maxSize * 0.25))
.opacity(animate ? 0.5 : 0.75)
Image(systemName: "circle")
.animateSfSymbol(size: animate ? (maxSize * 0.75) : (maxSize * 0.5))
.opacity(animate ? 0.25 : 0.5)
Image(systemName: "circle")
.animateSfSymbol(size: animate ? (maxSize) : (maxSize * 0.75))
.opacity(animate ? 0 : 0.25)
}
.foregroundColor(.red)
.onAppear {
withAnimation(.linear(duration: 4).repeatForever(autoreverses: false)) {
animate = true
}
}
}
}
請記住AnimatableModifier在您的代碼中包含。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/370284.html
上一篇:如何解決沒有驗證的準確性?
