Одна из возможностей ... проверить это с игровой площадкой
Объяснять особо нечего, «трюк» делается с правильной комбинацией различных стеков, выравниванием, .fixedSize(horizontal:, vertical:)
, Color.clear.frame(height:0)
заменой Spacer()
. Все вместе делает это "автоматическое c" расширение представления сообщения, основанное на тексте сообщения.
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())
РЕЗУЛЬТАТ:
![enter image description here](https://i.stack.imgur.com/aZMlQ.png)
Один и тот же код повторяется 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()
}
}
}
или , используя @ViewBulder для верхнего и нижнего колонтитула
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()
}
}
}