其中一种可能性是通过 Playground 进行检查
没有太多需要解释的,这个“技巧”是通过不同的堆栈、对齐方式、.fixedSize(horizontal: , vertical:)
、 Color.clear.frame(height:0)
替换 Spacer()
的正确组合完成的。所有这些都使得这个“自动”消息视图扩展基于消息文本。
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
var body: some View {
VStack {
HStack {
Spacer()
HStack {
VStack (alignment: .leading) {
Text("Lorem ipsum")
.font(.title)
.fixedSize()
Text("""
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
""")
.font(.system(size: 15))
.fixedSize(horizontal: false, vertical: true)
HStack {
Color.clear.frame(height: 0)
Text("22:13").fixedSize()
}
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
.padding()
}
.scaledToFit()
}
.border(Color.red)
HStack {
Spacer()
HStack {
VStack (alignment: .leading) {
Text("Lorem ipsum")
.font(.title)
.fixedSize()
Text("?")
.font(.system(size: 15))
.fixedSize(horizontal: false, vertical: true)
HStack {
Color.clear.frame(height: 0)
Text("22:13").fixedSize()
}
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
.padding()
}
.scaledToFit()
}
.border(Color.red)
HStack {
Spacer()
HStack {
VStack (alignment: .leading) {
Text("?")
.font(.title)
.fixedSize()
Text("Lorem ipsum")
.font(.system(size: 15))
.fixedSize(horizontal: false, vertical: true)
HStack {
Color.clear.frame(height: 0)
Text("22:13").fixedSize()
}
}
.padding()
.background(Color.yellow)
.cornerRadius(10)
.padding()
}
.scaledToFit()
}
.border(Color.red)
Spacer()
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
结果:
相同的代码被重复3次,只是因为我懒惰 :-)
最后,您可以使用类似以下的内容:
struct Message<Header: View, Footer: View>: View {
let header: Header
let footer: Footer
let message: String
let color: Color
var body: some View {
HStack {
Spacer()
HStack {
VStack (alignment: .leading) {
header.fixedSize()
Text(message)
.fixedSize(horizontal: false, vertical: true)
HStack {
color.frame(height: 0)
footer.fixedSize()
}
}
.padding()
.background(color)
.cornerRadius(10)
.padding()
}
.scaledToFit()
}
}
}
或者 使用 @ViewBuilder 来创建页眉和页脚
struct MessageBuilder<Header, Footer>: View where Header: View, Footer: View {
let header: () -> Header
let footer: () -> Footer
let message: String
let color: Color
init(@ViewBuilder header: @escaping () -> Header, @ViewBuilder footer: @escaping () -> Footer, message: String, color: Color) {
self.header = header
self.footer = footer
self.message = message
self.color = color
}
var body: some View {
HStack {
Spacer()
HStack {
VStack (alignment: .leading) {
header().fixedSize()
Text(message)
.fixedSize(horizontal: false, vertical: true)
HStack {
color.frame(height: 0)
footer().fixedSize()
}
}
.padding()
.background(color)
.cornerRadius(10)
.padding()
}
.scaledToFit()
}
}
}
然后在你的代码中使用它。
struct ContentView: View {
var body: some View {
VStack {
Message(header: Text("Header").font(.title), footer: Text("22:13"), message: "long or short message text", color: Color.blue.opacity(0.2))
MessageBuilder(header: {
HStack {
Image(systemName: "square.and.arrow.down")
Text("Fred")
}
}, footer: {
Image(systemName: "clock")
}, message: "message text", color: Color.gray.opacity(0.2))
Spacer()
}
}
}