I am developing a chat app.
If I don’t rotate SwiftUI’s ScrollView, there is an issue where it scrolls all the way to the 0th index when loading past chat history. So, I rotated the ScrollView and added a Spacer to position the chat messages starting from the top.
However, there is a problem.
When a new chat message is added, it automatically scrolls to the bottom. I need it to not scroll automatically if the user is reading a message in the middle.
Does anyone know how to achieve this? Here is my code.
Do you know how to programmatically enable or disable scrolling when using a ScrollView?
struct ChatView: View {
@State private var items: [Color] = [.red, .green, .blue, .yellow, .orange]
@State private var scrollViewHeight: CGFloat = 0
@State private var contentHeight: CGFloat = 0
@State private var isScrolledToBottom: Bool = true
var body: some View {
VStack {
ScrollViewReader { proxy in
ScrollView {
Spacer()
.frame(height: scrollViewHeight - contentHeight)
LazyVStack(spacing: 10) {
ForEach(items.indices, id: .self) { index in
Rectangle()
.frame(height: 50)
.foregroundStyle(items[index])
.rotationEffect(.degrees(180))
.scaleEffect(x: -1, y: 1, anchor: .center)
}
.rotationEffect(.degrees(180))
.scaleEffect(x: -1, y: 1, anchor: .center)
}
.overlay(
GeometryReader { geometry in
Color.clear.preference(key: ContentHeightKey.self, value: geometry.size.height)
}
)
.onPreferenceChange(ContentHeightKey.self) { height in
print("ContentHeight: (height)")
contentHeight = height
}
}
.onChange(of: items) { _ in
}
.overlay(
GeometryReader { geometry in
Color.clear
.preference(key: ViewHeightKey.self, value: geometry.size.height)
}
.onPreferenceChange(ViewHeightKey.self) { height in
print("scrollViewHeight: (height)")
scrollViewHeight = height
}
)
.rotationEffect(.degrees(180))
.scaleEffect(x: -1, y: 1, anchor: .center)
.onAppear {
proxy.scrollTo(items.last, anchor: .bottom)
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { _ in
withAnimation {
proxy.scrollTo(items.last, anchor: .bottom)
}
}
}
HStack {
Button(action: {
items.insert(.black, at: 0)
}, label: {
Text("addItem")
})
Button(action: {
items.append(contentsOf: Array(repeating: .red, count: 5))
}, label: {
Text("LoadPreView")
})
}
}
}
}
gmul is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.