InputAccessoryView /使用SwiftUI固定到键盘的视图

时间:2019-07-08 19:10:56

标签: swiftui

SwiftUI中是否有一个与InputAccessoryView等效的东西(或任何迹象表明即将出现?)

如果没有,您将如何模拟InputAccessoryView的行为(即固定在键盘顶部的视图)?所需的行为类似于iMessage,在屏幕底部固定有一个视图,该视图在键盘打开时位于上方,并直接位于键盘上方。例如:

键盘关闭:

keyboard closed

键盘打开:

keyboard open

5 个答案:

答案 0 :(得分:4)

我得到了一些可以满足预期结果的方法。因此,一开始,仅使用SwiftUI不可能做到这一点。您仍然必须使用UIKit通过所需的“ inputAccessoryView”创建UITextField。 SwiftUI中的文本字段没有特定的方法。

首先,我创建了一个新结构:

import UIKit
import SwiftUI

struct InputAccessory: UIViewRepresentable  {

    func makeUIView(context: Context) -> UITextField {

        let customView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 44))
        customView.backgroundColor = UIColor.red
        let sampleTextField =  UITextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40))
        sampleTextField.inputAccessoryView = customView
        sampleTextField.placeholder = "placeholder"

        return sampleTextField
    }
    func updateUIView(_ uiView: UITextField, context: Context) {
    }
}

最终,我可以在视图主体中创建一个新的文本字段:

import SwiftUI

struct Test: View {
    @State private var showInput: Bool = false
    var body: some View {
        HStack{
            Spacer()
            if showInput{
                InputAccessory()
            }else{
                InputAccessory().hidden()
            }
        }
    }
}

现在,您可以使用“ showInput”状态隐藏和显示文本字段。下一个问题是,您必须在特定事件中打开键盘并显示文本字段。 SwiftUI再次无法实现,您必须返回UiKit使其成为第一响应者。如果尝试使用我的代码,键盘上方应该会显示红色背景。现在,您只需向上移动字段,便可以使用版本。

总体而言,在当前状态下,无法使用键盘或某些textfield方法工作。

答案 1 :(得分:2)

iOS 15.0+

macOS 12.0+,Mac Catalyst 15.0+

ToolbarItemPlacement 在 iOS 15.0+ 中有一个新属性

<块引用>

keyboard

在 iOS 上,键盘项在存在时位于软件键盘上方,或者在连接了硬件键盘时位于屏幕底部。 在 macOS 上,键盘项目将放置在触控栏中。 https://developer.apple.com

struct LoginForm: View {
    @State private var username = ""
    @State private var password = ""
    var body: some View {
        Form {
            TextField("Username", text: $username)
            SecureField("Password", text: $password)

        }
        .toolbar(content: {
            ToolbarItemGroup(placement: .keyboard, content: {
                Text("Left")
                Spacer()
                Text("Right")
            })
        })
    }
}

答案 2 :(得分:1)

在 Swift Student 的 this post 的帮助下,我设法创建了一个很好的工作解决方案,并进行了大量修改和添加了您在 UIKit 中认为理所当然的功能。它是 UITextField 的包装器,但它对用户完全隐藏,并且它的实现非常 SwiftUI。您可以在我的 GitHub repo 中查看它 - 您可以将它作为 Swift 包引入到您的项目中。

(有太多代码无法放在这个答案中,因此链接到 repo)

答案 3 :(得分:0)

我已经在iOS 14上使用99%纯SwiftUI解决了这个问题。 在工具栏中,您可以显示任何您喜欢的视图。

那是我的实现方式

import SwiftUI

 struct ContentView: View {

    @State private var showtextFieldToolbar = false
    @State private var text = ""

    var body: some View {
    
        ZStack {
            VStack {
                TextField("Write here", text: $text) { isChanged in
                    if isChanged {
                        showtextFieldToolbar = true
                    }
                } onCommit: {
                    showtextFieldToolbar = false
                }
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .padding()
            }
        
             VStack {
                Spacer()
                if showtextFieldToolbar {
                    HStack {
                        Spacer()
                        Button("Close") {
                            showtextFieldToolbar = false
                            UIApplication.shared
                                    .sendAction(#selector(UIResponder.resignFirstResponder),
                                            to: nil, from: nil, for: nil)
                        }
                        .foregroundColor(Color.black)
                        .padding(.trailing, 12)
                    }
                    .frame(idealWidth: .infinity, maxWidth: .infinity,
                           idealHeight: 44, maxHeight: 44,
                           alignment: .center)
                    .background(Color.gray)   
                }
            }
        }
    }
}

 struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

答案 4 :(得分:0)

我有一个可以自定义工具栏的实现

public struct InputTextField<Content: View>: View {
    
    private let placeholder: LocalizedStringKey
    
    @Binding
    private var text: String
    
    private let onEditingChanged: (Bool) -> Void
    
    private let onCommit: () -> Void
    
    private let content: () -> Content
    
    @State
    private var isShowingToolbar: Bool = false
    
    public init(placeholder: LocalizedStringKey = "",
                text: Binding<String>,
                onEditingChanged: @escaping (Bool) -> Void = { _ in },
                onCommit: @escaping () -> Void = { },
                @ViewBuilder content: @escaping () -> Content) {
        self.placeholder = placeholder
        self._text = text
        self.onEditingChanged = onEditingChanged
        self.onCommit = onCommit
        self.content = content
    }
    
    public var body: some View {
        ZStack {
            TextField(placeholder, text: $text) { isChanged in
                if isChanged {
                    isShowingToolbar = true
                }
                onEditingChanged(isChanged)
            } onCommit: {
                isShowingToolbar = false
                onCommit()
            }
            .textFieldStyle(RoundedBorderTextFieldStyle())
            
            VStack {
                Spacer()
                if isShowingToolbar {
                    content()
                }
            }
        }
    }
}