swiftui - 在 SwiftUI 中制作聊天应用程序:如何让 ScrollView 在键盘出现时保持原位?
问题描述
我正在 SwiftUI 中制作聊天应用程序。这是我想要的效果:在 Telegram 或 Whatsapp 中打开任何聊天,点击输入框。键盘向上滑动时,聊天内容向上滑动。因此,如果您正在查看底部消息,您仍然可以看到它。
我无法在 SwiftUI 中获得这种效果。键盘向上滑动不滑动聊天内容:
import SwiftUI
struct SlidingKeyboardTest: View {
@State var inputText = "Placeholder"
var body: some View {
VStack {
ScrollView {
LazyVStack {
ForEach(1...100, id: \.self) { id in
HStack {
Spacer()
Text("message \(id)")
Spacer()
}
}
}
}
TextEditor(text: $inputText)
.frame(height: 50)
}
.background(LinearGradient(gradient: Gradient(colors: [.white, .blue, .white]), startPoint: .top, endPoint: .bottom))
.onTapGesture { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) }
}
}
struct SlidingKeyboardTest_Previews: PreviewProvider {
static var previews: some View {
SlidingKeyboardTest()
}
}
任何想法如何获得这种效果?
解决方案
您需要使用Introspect来接收对 UIScrollView 的访问并监听键盘高度的变化。
这是一个代码:
import Combine
import Introspect
import SwiftUI
struct SlidingKeyboardTest: View {
@State var inputText = "Placeholder"
@State var keyboardHeight = CGFloat(0)
@State var scrollView: UIScrollView? = nil
var body: some View {
VStack {
ScrollView {
LazyVStack {
ForEach(1 ... 100, id: \.self) { id in
HStack {
Spacer()
Text("message \(id)")
Spacer()
}
}
}
}.introspectScrollView {
scrollView = $0
}
TextEditor(text: $inputText)
.frame(height: 50)
}.onReceive(Publishers.keyboardHeight) { height in
if height > 0 {
self.scrollView!.setContentOffset(CGPoint(x: 0, y: self.scrollView!.contentOffset.y + height), animated: true)
} else {
self.scrollView!.contentOffset.y = max(self.scrollView!.contentOffset.y - keyboardHeight, 0)
}
keyboardHeight = height
}
.background(LinearGradient(gradient: Gradient(colors: [.white, .blue, .white]), startPoint: .top, endPoint: .bottom))
.onTapGesture { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) }
}
}
struct SlidingKeyboardTest_Previews: PreviewProvider {
static var previews: some View {
SlidingKeyboardTest()
}
}
推荐阅读
- python-3.x - Pytorch 无法转换 numpy.object 类型的 np.ndarray
- jquery - 选中复选框时的Jquery找不到最接近的输入值
- c - autoconf:在 `configure.ac` 中包含 `libftdi` 的最佳实践
- r - 在其他列上添加列条件
- python - 如何在 Python / Jupyter 中从 DataFrame 中分离一列?
- java - 如果唯一的区别是 for 循环中的方法调用,请避免重复代码
- python - 如何将列中的字符串转换为数据框中的不同列?
- c++ - 编译器会优化 for 循环以匹配总线宽度吗?
- sql - 从所有选定列的左右删除空格(TRIM)
- scala - akka Actor 中的可变集合返回 NullPointerException