在 SwiftUI 中制作聊天应用程序:如何让 ScrollView 在键盘出现时保持原位?

Posted

技术标签:

【中文标题】在 SwiftUI 中制作聊天应用程序:如何让 ScrollView 在键盘出现时保持原位?【英文标题】:Making a chat app in SwiftUI: How to make ScrollView keep its place when the keyboard shows up? 【发布时间】:2020-10-10 02:52:32 【问题描述】:

我正在用 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()
    

任何想法如何获得这种效果?

【问题讨论】:

【参考方案1】:

您需要使用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()
    

【讨论】:

欢迎来到 SO!优秀而详细的第一个答案,恭喜!

以上是关于在 SwiftUI 中制作聊天应用程序:如何让 ScrollView 在键盘出现时保持原位?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中制作水平列表?

如何在 SwiftUI 中制作简单的上下浮动动画?

如何在 bash 中制作聊天脚本?

如何让 SwiftUI 循环中的元素全屏显示?与 Apple 一样,今日应用

如何制作一个接受任何对象的 swiftui viewmodifier?

你如何制作这种风格的文字? SwiftUI