Below are a video showing the issue and the code used to demo the issue and implementing my current chat behavior.
The video below shows the issue:
Code aus dem Video:
Code: Select all
struct DemoView: View {
struct Message: Identifiable {
let id: UUID
let content: String
}
@State private var messages: [Message] = []
@State private var scrollPosition: UUID?
@State private var message = ""
var body: some View {
NavigationStack {
VStack {
GeometryReader { geometryProxy in
let scrollViewHeight = geometryProxy.size.height
ScrollView {
VStack(alignment: .leading, spacing: 10) {
ForEach(messages) { message in
VStack {
VStack(alignment: .trailing) {
Text(message.content)
.multilineTextAlignment(.leading)
.padding(.bottom, 20)
.frame(maxWidth: .infinity, alignment: .trailing)
}
VStack(alignment: .leading) {
Text("Assistant reply")
.multilineTextAlignment(.leading)
.padding(.bottom, 20)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.frame(
minHeight: message.id == messages.last?.id ? scrollViewHeight : 0,
alignment: .top
)
}
}
.frame(maxWidth: .infinity)
.padding(.horizontal, 20)
.ignoresSafeArea(.keyboard, edges: .bottom)
}
.scrollPosition(id: $scrollPosition, anchor: .bottom)
}
.safeAreaInset(edge: .bottom) {
VStack {
TextField("Ask anything...", text: $message)
.multilineTextAlignment(.leading)
.font(.body)
.onSubmit {
guard !message.isEmpty else {
return
}
let id = UUID()
messages.append(Message(id: id, content: message))
message = ""
withAnimation {
scrollPosition = id
}
}
}
.contentShape(Rectangle())
.frame(maxWidth: .infinity)
.padding(16)
.background(.gray)
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
}
}
.padding(16)
}
}
}