无法使 UIViewRepresentable 的 CustomView 在 SwiftUI 中正常工作
Posted
技术标签:
【中文标题】无法使 UIViewRepresentable 的 CustomView 在 SwiftUI 中正常工作【英文标题】:Cannot make CustomView for UIViewRepresentable to work correctly in SwiftUI 【发布时间】:2021-04-09 09:08:47 【问题描述】:我有这个 SwiftUI 组件
var body: some View
let image = TypographyImage.image(for: typography, kind: kind)
let width = image.size.width + 4
let height = TypographyImage.height(for: typography) * (kind == .oneLine ? 1.0 : 2.0)
ScrollView(.horizontal)
HStack
Image(uiImage: image)
.frame(width: width, height: height, alignment: Alignment(horizontal: .center, vertical: .top))
.offset(y: TypographyImage.offset(for: typography))
.background(Color.red)
if isSwiftUI
Text(text)
.typography(typography, theme: AmityTheme.shared)
.background(Color.red)
else
MyUILabel(text: text, typography: typography, theme: AmityTheme.shared).background(Color.red)
显示此 UI
请注意,在MyUILabel
中,我应用了背景红色。
HStack
内的 MyUILabel
的背景颜色和对齐方式在 MyUILabel
返回 UILabel
作为第一个子视图时正确显示
如下图
struct MyUILabel: UIViewRepresentable
var text: String
var typography: AmityTheme.Typography
var theme: AmityTheme
func makeUIView(context: Context) -> UILabel
let view = UILabel(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.setContentHuggingPriority(.defaultHigh, for: .vertical)
view.setContentHuggingPriority(.defaultHigh, for: .horizontal)
updateUIView(view, context: context)
return view
func updateUIView(_ view: UILabel, context: Context)
view.attributedText = NSAttributedString(string: text, attributes: theme.textAttributes(for: typography, palette: .black))
但是,如果我将其更改为返回我的自定义视图,例如
struct MyUILabel: UIViewRepresentable
var text: String
var typography: AmityTheme.Typography
var theme: AmityTheme
func makeUIView(context: Context) -> PaddedUILabel
let view = PaddedUILabel(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.setContentHuggingPriority(.defaultHigh, for: .vertical)
view.setContentHuggingPriority(.defaultHigh, for: .horizontal)
updateUIView(view, context: context)
return view
func updateUIView(_ view: PaddedUILabel, context: Context)
view.update(text: text, typography: typography, theme: theme)
class PaddedUILabel: UIView
private var label: UILabel!
private var topConstraint: NSLayoutConstraint!
private var bottomConstraint: NSLayoutConstraint!
override init(frame: CGRect)
super.init(frame: frame)
commonInit()
required init?(coder: NSCoder)
super.init(coder: coder)
commonInit()
private func commonInit()
let label = UILabel(frame: .zero)
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.setContentHuggingPriority(.defaultHigh, for: .vertical)
label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
self.label = label
addSubview(label)
topConstraint = label.topAnchor.constraint(equalTo: topAnchor)
bottomConstraint = label.bottomAnchor.constraint(equalTo: bottomAnchor)
let constraints: [NSLayoutConstraint] = [
label.leadingAnchor.constraint(equalTo: leadingAnchor),
label.trailingAnchor.constraint(equalTo: trailingAnchor),
topConstraint,
bottomConstraint
]
NSLayoutConstraint.activate(constraints)
func update(text: String, typography: AmityTheme.Typography, theme: AmityTheme)
let attributes = theme.textAttributes(for: typography, palette: .black)
label.attributedText = NSAttributedString(string: text, attributes: attributes)
结果是
背景颜色消失了,HStack
中心垂直对齐不被尊重。我似乎不知道为什么会这样。
谁能建议我如何解决这个问题?
谢谢
【问题讨论】:
为什么要使用自定义视图 PaddedUILabel (UILabel)? 因为这是我们应用程序的一种中心框架,我必须确保我们的 NSAttributedString 主题在 SwiftUI 和 UIKit 上都能正常工作。PaddedUILabel
将在框架端实现,以使显示的文本与设计者的预期完全相同(NSAttributedString
的 key 属性是不够的)。这就是PaddedUILabel
的原因
【参考方案1】:
似乎在CustomView
中布局任何约束并使其UIViewRepresentable
根据Here 将不起作用
在 SwiftUI 中,父母问孩子:你想要多大的尺寸?孩子告诉父母,父母设定尺寸。完毕。 然而,AutoLayout 需要不止一次通过才能确定完整的布局。它根本没有机会。
我对 UIViewRepresentable 的经验法则是:让它超级简单,只包装一个视图。不止一个视图要求布局问题。
另外this 指出 SwiftUI 布局的工作方式存在限制,与原版布局约束和intrinsincContentSize
不兼容
【讨论】:
以上是关于无法使 UIViewRepresentable 的 CustomView 在 SwiftUI 中正常工作的主要内容,如果未能解决你的问题,请参考以下文章
如何使 UIViewRepresentable @ViewBuilder 与动态内容一起使用?
无法使用 UIViewRepresentable 和 UIDocumentPicker 选择文件夹
SwiftUI MapKit UIViewRepresentable 无法显示警报
无法将点击手势识别器添加到 SwiftUI MKMapView UIViewRepresentable