调整大小时的 SwiftUI 文本剪辑
Posted
技术标签:
【中文标题】调整大小时的 SwiftUI 文本剪辑【英文标题】:SwiftUI Text clips on resize 【发布时间】:2020-02-16 22:59:36 【问题描述】:在以下示例中,点击“展开”按钮会导致文本“39”在调整大小以转换为“40”时进行剪辑。这种使用的真正上下文是一个文本标签,它反映了动画图中选择器的值。我希望文本只占用它需要的空间,但在值之间进行动画处理时不进行剪辑。
禁用标签动画不是一个选项,因为标签在我的图表中的位置也会动画。
复制:
import SwiftUI
struct TextClipping: View
enum ExpansionState
case expanded
case contracted
mutating func toggle()
switch self
case .expanded:
self = .contracted
case .contracted:
self = .expanded
@State var expansion: ExpansionState = .contracted
var text: String
switch expansion
case .expanded:
return "40"
case .contracted:
return "39"
var body: some View
VStack(spacing: 16)
Text(text)
.font(.system(.title, design: .rounded))
.fontWeight(.bold)
.foregroundColor(.black)
Button(self.expansion == .contracted ? "Expand" : "Contract")
withAnimation
self.expansion.toggle()
struct TextClipping_Previews: PreviewProvider
static var previews: some View
TextClipping()
有什么想法可以让标签的文本流畅地变化而不被剪裁吗?
【问题讨论】:
无法在 Xcode 13 / ios 15 中重现。您能否附上 gif 与问题的演示或提供更可见重现的代码? 【参考方案1】:所以,我认为您的问题并不完全清楚,但我认为您所指的“剪辑”是 39 和 40 在您之间制作动画时左右移动轻微他们。在父视图中,这可能会剪辑,但我在这里看不到它。
首先,您不需要制作自己的变异结构来修改视图中的变量,这就是@State
变量的全部意义,而这整个问题可以用一个简单的布尔值来解决。所有这些代码基本相同,除了一个关键行:.id
行。这告诉 SwiftUI 视图是不一样的。在添加之前,它认为它们是相同的视图,但是文本正在更改,导致偏移量看起来很奇怪。如果这仍然不能回答您的问题,请告诉我,但我无法想象您还指的是什么,因为您没有包含视觉示例,并且我无法重现您所指的“剪辑”效果.
struct TextClipping: View
@State private var expanded: Bool = false
var body: some View
let text: String = expanded ? "40" : "39"
VStack(spacing: 16)
Text(text)
.font(.system(.title, design: .rounded))
.fontWeight(.bold)
.foregroundColor(.black)
// Opacity is the default animation, but can be replaced by another if you feel like it
//.transition(.opacity)
.id("label\(text)")
Button(expanded ? "Contract" : "Expand")
withAnimation
expanded.toggle()
struct TextClipping_Previews: PreviewProvider
static var previews: some View
TextClipping()
【讨论】:
这应该是公认的答案,只需将 id 添加到 Text 即可解决问题。谢谢!【参考方案2】:通过申请解决
.minimumScaleFactor(0.1)
到正文。
【讨论】:
这不起作用(至少在带有自定义字体的 iOS 15 上)【参考方案3】:您可以尝试将此修饰符添加到文本中
.fixedSize()
【讨论】:
【参考方案4】:要在不禁用偏移动画的情况下禁用大小动画,我使用了嵌入另一个 UIViewController
的 UIHostingController
:这允许我在不使用动画的情况下更新大小,从而允许 SwiftUI 为偏移设置动画。
附言从技术上讲,您可以将此代码转换为修饰符,但我认为将视图嵌入容器中应该很清楚,因为在某些情况下它会显着影响布局。
struct DisableSizeAnimationContainer<Content: View>: View
let content: Content
init(@ViewBuilder _ content: () -> Content)
self.content = content()
var body: some View
ContainerRepreseentable
content
.fixedSize()
private struct ContainerRepreseentable<Content: View>: UIViewControllerRepresentable
let content: Content
init(@ViewBuilder _ content: () -> Content)
self.content = content()
func makeUIViewController(context: Context) -> UIHostingControllerContainer<Content>
UIHostingControllerContainer(rootView: content)
func updateUIViewController(_ uiViewController: UIHostingControllerContainer<Content>, context: Context)
uiViewController.rootView = content
private class UIHostingControllerContainer<RootView: View>: UIViewController
private let hostingController: UIHostingController<RootView>
init(rootView: RootView)
hostingController = UIHostingController(rootView: rootView)
super.init(nibName: nil, bundle: nil)
var rootView: RootView
get hostingController.rootView
set
hostingController.rootView = newValue
preferredContentSize = hostingController.view.intrinsicContentSize
view.frame = .init(origin: .zero, size: preferredContentSize)
hostingController.view.frame = view.frame
required dynamic init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func viewDidLoad()
super.viewDidLoad()
addChild(hostingController)
view.addSubview(hostingController.view)
用法:
Button(action:
withAnimation
expansion.toggle()
)
DisableSizeAnimationContainer
Text(expansion ? "Small text" : "Significantly larger text")
.offset(x: expansion ? 100 : 0)
结果:
【讨论】:
【参考方案5】:为了防止剪裁,您可以使用这样的叠加层:
struct TextClipping: View
@State private var expanded: Bool = false
var body: some View
let text: String = expanded ? "40" : "39"
VStack(spacing: 16)
Text("40")
.fontWeight(.bold)
.font(.system(.title, design: .rounded))
.hidden()
.overlay(
Text(text).fontWeight(.bold).font(.system(.title, design: .rounded))
).id("label\(text)")
Button(expanded ? "Contract" : "Expand")
withAnimation
expanded.toggle()
【讨论】:
以上是关于调整大小时的 SwiftUI 文本剪辑的主要内容,如果未能解决你的问题,请参考以下文章