SwiftUI 键盘弹出一次输入并不断出现和消失

Posted

技术标签:

【中文标题】SwiftUI 键盘弹出一次输入并不断出现和消失【英文标题】:SwiftUI Keyboard pops up once for Input and keeps appearing and disappearing 【发布时间】:2020-12-19 21:42:32 【问题描述】:

我是 Swift 编程的新手,我正在尝试通过一些 YouTube 教程学习如何构建自己的聊天应用程序。我已经走了很远,但遇到了障碍。我不明白为什么当我尝试输入 TextField 时,它第一次可以正常工作,但如果我随后再点击那里,键盘会弹出然后立即消失。

.clipShape(Rectangle()) 的代码行原本是.clipShape(RoundedShape()),但那会切断消息,所以我默认为Rectangle()。我认为这与我的 TextField 或 Rectangle() 有关。用键盘看看下面的截图(第一次尝试):

下面是我的代码:

import SwiftUI

struct ChatUIView: View 
    
    @State var message = ""
    //StateObject is the owner of the object...
    @StateObject var allMessages = Messages()
    
    var body: some View 
        VStack
            
            ZStack
                
                /*
                HStack
                    Spacer()
                */
                
                VStack(spacing:5)
                    Text("Chat")
                        .fontWeight(.bold)
                
                .foregroundColor(.white)
            
            .padding(.all)
            
            //Spacer()
            VStack
                
                //Spacer()
                //Displaying Message...
                
                ScrollView(.vertical, showsIndicators: false, content: 
                    
                    ScrollViewReaderreader in
                        
                        VStack(spacing: 20)
                            
                            ForEach(allMessages.messages)msg in
                                
                                //Chat Bubbles...
                                
                                ChatBubble(msg: msg)
                            
                                
                            
                            //whenever new data is inserted, scroll to bottom...
                            .onChange(of: allMessages.messages) (value) in
                                
                                //scrolling only user message...
                                
                                if value.last!.myMsg
                                    reader.scrollTo(value.last?.id)
                                
                                
                            
                        
                        .padding([.horizontal, .bottom])
                        .padding(.top, 25)
                    
                )
                
                HStack(spacing:15)
                    
                    HStack(spacing: 15)
                        TextField("Message", text: self.$message)
                    
                    .padding(.vertical, 12)
                    .padding(.horizontal)
                    .background(Color.black.opacity(0.06))
                    .clipShape(Capsule())
                    
                    
                    //send button
                    //hiding view...
                    if message != ""
                        Button(action: 
                            
                            //appending message...
                            
                            //adding animation...
                            withAnimation(.easeIn)
                                allMessages.messages.append(Message(id: Date(), message: message, myMsg: true))
                            
                            message = ""
                            
                        , label: 
                            
                            Image("send")
                                .resizable()
                                .frame(width: 25, height: 25)
                                .rotationEffect(.init(degrees: 45))
                                .padding()
                                //.aspectRatio(contentMode: .fit)
                                //.font(.system(size: 0.5))
                                //.padding(.all)
                                .background(Color.black.opacity(0.07))
                                .clipShape(Circle())
                        )
                    
                
                .padding(.horizontal)
                .animation(.easeOut)
            
            .padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom)
            .background(Color.white)
            //.clipShape(RoundedShape())
            .clipShape(Rectangle())
            .keyboardType(.default)
        
        //.edgesIgnoringSafeArea(.bottom)
        .background(Color.blue.edgesIgnoringSafeArea(.top))
    


//Chat Bubbles...

struct ChatBubble : View 
    
    var msg : Message
    var body: some View
        
        //Automatics scroll to bottom...
        //First assigning id to each row
        
        HStack(alignment: .top, spacing: 10)
            
            if msg.myMsg
                
                //pushing msg to the left...
                
                //minimum space ...
                Spacer(minLength: 25)
                
                Text(msg.message)
                    .padding(.all)
                    .background(Color.black.opacity(0.06))
                    //.cornerRadius(15)
                    .clipShape(BubbleArrow(myMsg: msg.myMsg))
             else 
                
                //pushing msg to the right...
                
                Text(msg.message)
                    .fixedSize(horizontal: false, vertical: true)
                    .lineLimit(nil)
                    .foregroundColor(.white)
                    .padding(.all)
                    //.background(Color.black.opacity(0.06))
                    .background(Color.blue)
                    .clipShape(BubbleArrow(myMsg: msg.myMsg))
                
                Spacer(minLength: 25)
            
        
        .id(msg.id)
        //.padding(msg.myMsg ? .leading : .trailing, 55)
        //.padding(.vertical,10)
    


// Bubble Arrow...

struct BubbleArrow : Shape 
    
    var myMsg : Bool
    
    
    func path(in rect: CGRect) -> Path 
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: myMsg ? [.topLeft, .bottomLeft, .bottomRight] : [.topRight, .bottomLeft, .bottomRight], cornerRadii: CGSize(width: 10, height: 10))
        
        return Path(path.cgPath)
    



// Custom Rounded Shape...

struct RoundedShape : Shape 
    
    func path(in rect: CGRect) -> Path 
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize())
        
        return Path(path.cgPath)
    


// Model Data For Message...

struct Message : Identifiable, Equatable 
    
    var id: Date
    var message: String
    var myMsg: Bool
    //var profilePic: String
    //var photo: Data?
    


class Messages: ObservableObject 
    
    @Published var messages : [Message] = []
    
    //sample data...
    init() 
        let strings = ["Hi!", "hello!", "How are you doing?!", "Fine, I just want to talk about life", "ok, I may be able to help with that", "This is awesome, thanks", "So what do you want to talk about?", "movies sound like a good topic. Let's start there!", "Ok, so tell me: What's you favorite movie? LKASJLDJGLSJGOJOSGJDOJGOSDJNOGNSDOGNISNO", "Definitely, interstellar for sure."]
        
        for i in 0..<strings.count
            
            //simple logic for two sided message View...
            
            messages.append(Message(id: Date(), message: strings[i], myMsg: i % 2 == 0 ? false : true))
        
    
    
    func writeMessage(id: Date, msg: String, photo: Data?, myMsg: Bool)
        
        messages.append((Message(id: id, message: msg, myMsg: myMsg)))
        
        
    

同样,我不确定我的 SwiftUI 代码本身存在什么问题。我所有的其他文本字段都很好。任何帮助,将不胜感激!谢谢。

【问题讨论】:

【参考方案1】:

我不确定发生这种情况的确切原因,但您可以只塑造背景层而不是实际的 TextField,您将获得相同的 UI 结果。

.background(
    Color.black
        .opacity(0.06)
        .clipShape(Capsule())
)
//.clipShape(Capsule())

【讨论】:

我不知道为什么会这样,但确实有效!谢谢!我赞成你的回答。您介意解释一下为什么会这样吗? 我也不是 100% 确定原因。这对我来说似乎是一个错误......我认为它与垂直填充和 .clipShape 在同一层上有关......因为如果我删除了垂直填充,问题也会消失。因此,解决方案是将 .clipShape 移动到与垂直填充渲染所在不同的层上。现在,我们不再将 HStack 变成 Capsule,而是将 Color.black 变成 Capsule。 (我希望我能给你一个更好的答案,哈哈)。

以上是关于SwiftUI 键盘弹出一次输入并不断出现和消失的主要内容,如果未能解决你的问题,请参考以下文章

键盘出现/消失时调整带有 TextField 的 SwiftUI 列表

JSP页面弹出模态窗口

调整键盘出现/消失的视图:动画曲线问题

webview软键盘弹出又马上消失

出现键盘时,简单的 SwiftUI 背景图像一直在移动

SwiftUI 弹出框在 NavigationView 中时消失