当显示键盘时,UIViewControllerRepresentable MessageKit UICollectionView 滚动经过底部项目

问题描述

我正在使用 SwiftUI 构建应用程序并且我想使用 MessageKit,所以我使用了 UIViewControllerRepresentable显示 MessageKit 视图。但是,当显示键盘时,消息可以滚动到视图底部

问题截图如下:

scroll past bottom with keyboard shown

我仍然可以向下滚动消息,但是尝试将 UICollectionView 推到底部会导致同样的问题。隐藏键盘时不会出现此问题。

这是捕获的 UI 层次结构的屏幕截图,其中隐藏了导航栏和根视图:

view hierarchy

集合视图的大小仍然正确,但消息能够滚动到底部并且滚动指示器在顶部向上。

这是带有相关代码的根 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 有更多扩展,但我只会根据要求包含它们,因为我认为它们与我的问题无关。我可能在这里做错了什么,我应该如何尝试修复它?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...