UIViewController上的简单输入附加视图
我想要一个像iMessage中看到的输入附加视图。该条在屏幕底部始终可见。当TextField获得焦点时,键盘跳入,条自动向上移动,同时固定在键盘顶部。
即使没有文本输入焦点也必须显示输入附加
在UIKit中,ViewController可以覆盖inputAccessory并成为第一个响应者。因此,输入附加视图是永久可见的。我找不到在SwiftUI中实现这一点的方法。
键盘和附件必须缩小滚动视图
当键盘弹出时,包含消息并填充整个屏幕的滚动视图必须相应缩小。当拖动ScrollView并交互式移动键盘时,也适用相同的操作。在拖动过程中必须调整视图大小。
最重要的:在拖动ScrollView并交互式移动键盘时必须正常工作
最重要的要求是,在拖动滚动视图并将键盘交互式移动时,必须平稳地运行。这与iMessage或WhatsApp中的行为相同。在拖动时,输入附加必须移动,并且滚动视图必须调整大小。在键盘消失后,工具栏/输入附加必须保持在底部可见。
不是重复的问题
我阅读了InputAccessoryView / View Pinned to Keyboard with SwiftUI,但这与我的问题不相似。我需要即使键盘未显示也能看到工具栏。而且,在该问题中接受的答案在iOS 15上无法正常工作。拖动以关闭键盘会留下白色间隙。
UIKit可行
在UIKit实现中,持有视图是UITableViewController,键盘关闭交互设置。这意味着,当键盘显示时,您可以拖动该视图,并在同一移动中将键盘和附件视图向下拖动,直到键盘消失。然而,附加视图仍然保留在底部。
在UIKit中实现很简单,如下所示。一切都可以轻松完成。
class ChatTableViewController: UITableViewController {
...
override var inputAccessoryView: UIView? {
return inputBar
}
override var canBecomeFirstResponder: Bool {
return true
}
...
}
UIKit实现看起来不错
需要在SwiftUI中寻求帮助(Xcode 13 beta 5,iOS 15)
对于SwiftUI,我已经发现在iOS 15中有一个placement: .keyboard 参数,可以在键盘顶部放置工具栏。但问题是,只有当TextField被聚焦时,此功能才有效。如果没有TextField被聚焦,也就是没有键盘或者键盘被关闭,那么工具栏就不可见。
struct Chat: View {
@State private var text: String = ""
var body: some View {
ZStack {
ScrollView {
ScrollViewReader { value in
LazyVStack(spacing: 15) {
ForEach((1...10), id: \.self) { x in
let isOwner = x % 2 == 0;
ChatMessage(isOwner: isOwner)
.padding(.leading, isOwner ? 90 : 0)
.padding(.trailing, isOwner ? 0 : 90)
}
}
.padding(.horizontal)
.padding(.top, 10)
.onAppear {
value.scrollTo(10, anchor: .bottomTrailing)
}
}
}
.background(Color.red)
.ignoresSafeArea(.keyboard)
VStack {
// Toolbar only visible if this box has focus
TextField("", text: $text)
.padding(10)
.background(Color(.systemGray6))
.cornerRadius(5)
}
}
.navigationBarTitle("test")
.navigationBarTitleDisplayMode(.inline)
.onAppear {
UIScrollView.appearance().keyboardDismissMode = .interactive
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
HStack {
TextField("", text: $text)
.padding(10)
.background(Color(.systemGray6))
.cornerRadius(5)
Text("Hello")
}
.padding(.vertical, 5)
.padding(.horizontal)
.background(Color.blue)
}
}
}
}