我正在使用 SwiftUI 构建一个应用程序,并且我想使用 MessageKit,所以我使用 aUIViewControllerRepresentable
来显示 MessageKit 视图。但是,当显示键盘时,消息能够滚动到视图底部。
我仍然可以向下滚动消息,但尝试将消息推UICollectionView
到底部会导致同样的问题。隐藏键盘时不会出现此问题。
这是捕获的 UI 层次结构的屏幕截图,其中隐藏了导航栏和根视图:
集合视图的大小仍然正确,但消息能够滚动到底部并且滚动指示器在顶部向上。
这是带有相关代码的根 SwiftUI 视图:
struct SingleChatView: SwiftUI.View {
@ObservedObject var chat: Chat
@State private var mkView: MessageKitView
init(chat: Chat) {
self.chat = chat
_mkView = State(initialValue: MessageKitView(chat: chat))
}
var body: some SwiftUI.View {
mkView
.navigationBarTitle(chat.name)
.uiKitOnAppear {
mkView.controller.becomeFirstResponder()
mkView.controller.messagesCollectionView.scrollToBottom(animated: true)
chat.clearNotifications()
// Set chat as active
ChatManager.shared.activeChat = chat
}
.onDisappear {
chat.setTypingStatus(to: false)
// Set chat as inactive
ChatManager.shared.activeChat = nil
}
}
}
// Different file
struct UIKitAppear: UIViewControllerRepresentable {
let action: () -> Void
func makeUIViewController(context: Context) -> UIAppearViewController {
let vc = UIAppearViewController()
vc.action = action
return vc
}
func updateUIViewController(_ controller: UIAppearViewController, context: Context) {
}
}
final class UIAppearViewController: UIViewController {
var action: () -> Void = {}
override func viewDidLoad() {
view.addSubview(UILabel())
}
override func viewDidAppear(_ animated: Bool) {
action()
}
}
public extension View {
func uiKitOnAppear(_ perform: @escaping () -> Void) -> some View {
self.background(UIKitAppear(action: perform))
}
}
这是根 UIKit 视图控制器:
struct MessageKitView: UIViewControllerRepresentable {
@ObservedObject var chat: Chat
@EnvironmentObject var userData: UserData
@State var controller = ChatViewController()
@State var refreshControl = UIRefreshControl()
init(chat: Chat) {
self.chat = chat
}
func makeUIViewController(context: Context) -> MessagesViewController {
return controller
}
func updateUIViewController(_ uiViewController: MessagesViewController, context: Context) {
uiViewController.messagesCollectionView.messagesDataSource = context.coordinator
uiViewController.messagesCollectionView.messagesLayoutDelegate = context.coordinator
uiViewController.messagesCollectionView.messagesDisplayDelegate = context.coordinator
uiViewController.messagesCollectionView.messageCellDelegate = context.coordinator
uiViewController.showMessageTimestampOnSwipeLeft = true
uiViewController.setTypingIndicatorViewHidden(chat.typers.isEmpty, animated: true)
// Refresh Control
refreshControl.addTarget(context.coordinator, action: #selector(context.coordinator.onRefresh), for: .valueChanged)
uiViewController.messagesCollectionView.refreshControl = refreshControl
uiViewController.messageInputBar.delegate = context.coordinator
uiViewController.messageInputBar.inputTextView.isImagePasteEnabled = false
//uiViewController.maintainPositionOnKeyboardFrameChanged = true
uiViewController.scrollsToBottomOnKeyboardBeginsEditing = true
//uiViewController.scrollsToLastItemOnKeyboardBeginsEditing = true
uiViewController.messagesCollectionView.reloadData()
//uiViewController.messagesCollectionView.scrollToLastItem(at: .bottom, animated: true)
//uiViewController.messagesCollectionView.scrollToBottom(animated: true)
// Removes avatar from outgoing messages
if let layout = uiViewController.messagesCollectionView.collectionViewLayout as? MessagesCollectionViewFlowLayout {
layout.textMessageSizeCalculator.outgoingAvatarSize = .zero
layout.textMessageSizeCalculator.outgoingMessageBottomLabelAlignment = LabelAlignment(textAlignment: .right, textInsets: .zero)
layout.emojiMessageSizeCalculator.outgoingAvatarSize = .zero
layout.emojiMessageSizeCalculator.outgoingMessageBottomLabelAlignment = LabelAlignment(textAlignment: .right, textInsets: .zero)
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator {
let parent: MessageKitView
init(_ parent: MessageKitView) {
self.parent = parent
}
@objc func onRefresh() {
parent.chat.loadMessages(userData: parent.userData, withPromise: FailurePromise(success: {
self.parent.refreshControl.endRefreshing()
}, failure: { failure in
self.parent.refreshControl.endRefreshing()
print(failure)
}))
}
}
}
注释掉的行代表我试图调整的参数。还有更多的扩展,Coordinator
但我只会根据要求将它们包括在内,因为我认为它们与我的问题无关。我在这里做错了什么,我应该如何尝试解决它?