3

我正在使用 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但我只会根据要求将它们包括在内,因为我认为它们与我的问题无关。我在这里做错了什么,我应该如何尝试解决它?

4

0 回答 0