SwiftUI中的动画文本

时间:2020-04-02 00:35:01

标签: animation text swiftui ellipsis

SwiftUI具有出色的动画功能,但是它处理Text视图内容更改的方式存在问题。它为文本框的更改设置动画,但无需动画即可立即更改文本。结果,当Text视图的内容变长时,对过渡进行动画处理会导致省略号(…)出现,直到文本框达到其完整宽度。例如,在这个小应用程序中,按下 Toggle (切换)按钮会在短文本和长文本之间切换:

enter image description here

这是代码:

import SwiftUI

struct ContentView: View {
    @State var shortString = true
    var body: some View {
        VStack {
            Text(shortString ? "This is short." : "This is considerably longer.").font(.title)
                .animation(.easeInOut(duration:1.0))
            Button(action: {self.shortString.toggle()}) {
                Text("Toggle").padding()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

问题是:如何避免省略号?将一个字符串动画化为两个字符串时,情况甚至更糟,因为短字符串动画化为较长字符串时完全被省略号代替。

一种可能性是通过添加修饰符(例如.id(self.shortString ? 0 : 1),然后添加.transition()修饰符,为处于一种或另一种状态的视图分配单独的ID。它将在前后将文本视为两个不同的视图。不幸的是,就我而言,我需要在更改过程中移动文本位置,并且不同的ID使其无法制作动画。

我想解决方案是对AnimatableData的创造性使用。有什么想法吗?

PS很抱歉,屏幕截图太大!对于缩小动画gif的尺寸有什么建议吗? :)

3 个答案:

答案 0 :(得分:3)

以下是可能方法的演示(草稿-您可以将其重新设计为扩展,修改器或单独的视图)

通过Xcode 11.4 / iOS 13.4测试

demo

struct ContentView: View {
    @State var shortString = true
    var body: some View {
        VStack {
            if shortString {
                Text("This is short.").font(.title).fixedSize()
                .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }
            if !shortString {
                Text("This is considerably longer.").font(.title).fixedSize()
                .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }

            Button(action: {self.shortString.toggle()}) {
                Text("Toggle").padding()
            }
        }
    }
}

有没有缩小gif动画尺寸的建议?

I use this way:
- decrease zoom of Preview to 75% (or resize window of Simulator)
- use QuickTimePlayer region-based Screen Recording
- use https://ezgif.com/video-to-gif for converting to GIF

答案 1 :(得分:2)

如果将.animation(nil)添加到Text对象定义中,则内容将直接在值之间更改,从而避免了省略号。

但是,这可能会阻止文本位置的动画,您也提到要同时进行动画处理。

答案 2 :(得分:1)

您可以在额外的0.1秒后将一个字符添加到带有动画的字符串中,但是请记住在添加字符时禁用按钮切换,如下所示:demo

代码:

public struct TextAnimation: View {

public init(){ }
@State var text: String = ""
@State var toggle = false

public var body: some View {
  VStack{
    Text(text).animation(.spring())
    HStack {
      Button {
        toggle.toggle()
      } label: {
        Text("Toggle")
      }
    }.padding()
  }.onChange(of: toggle) { toggle in
    if toggle {
      text = ""
      "This is considerably longer.".enumerated().forEach { index, character in
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(index) * 0.1) {
          text += String(character)
        }
      }
    } else {
      text = "This is short."
    }
  }
}
}