InputAccessoryView / 视图固定到键盘与 SwiftUI

zzz*_*zzz 7 swiftui

SwiftUI 中是否有等效于 InputAccessoryView 的东西(或任何迹象即将到来?)

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

键盘关闭:

键盘关闭

键盘打开:

键盘打开

Mar*_*ark 9

我得到了一些工作,非常接近想要的结果。因此,起初,仅使用 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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

有了这个,我终于可以在我的视图正文中创建一个新的文本字段:

import SwiftUI

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

现在您可以隐藏和显示具有“showInput”状态的文本字段。下一个问题是,您必须在某个事件中打开键盘并显示文本字段。这在 SwiftUI 中又是不可能的,你必须回到 UiKit 并使其成为第一响应者。如果您尝试我的代码,您应该会在键盘上方看到红色背景。现在,您只需将字段向上移动即可获得一个工作版本。

总体而言,在当前状态下,无法使用键盘或某些文本字段方法。


Dun*_*Dev 6

我已经在 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()
    }
}
Run Code Online (Sandbox Code Playgroud)


mah*_*han 5

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")
            })
        })
    }
}

Run Code Online (Sandbox Code Playgroud)

iMessage 类似于 iOS 15+ 中的 InputAccessoryView。


struct KeyboardToolbar<ToolbarView: View>: ViewModifier {
    private let height: CGFloat
    private let toolbarView: ToolbarView
    
    init(height: CGFloat, @ViewBuilder toolbar: () -> ToolbarView) {
        self.height = height
        self.toolbarView = toolbar()
    }
    
    func body(content: Content) -> some View {
        ZStack(alignment: .bottom) {
            GeometryReader { geometry in
                VStack {
                    content
                }
                .frame(width: geometry.size.width, height: geometry.size.height - height)
            }
            toolbarView
                .frame(height: self.height)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}


extension View {
    func keyboardToolbar<ToolbarView>(height: CGFloat, view: @escaping () -> ToolbarView) -> some View where ToolbarView: View {
        modifier(KeyboardToolbar(height: height, toolbar: view))
    }
}
Run Code Online (Sandbox Code Playgroud)

.keyboardToolbar像往常一样使用视图修饰符。


struct ContentView: View {
    @State private var username = ""
    
    var body: some View {
        NavigationView{
            Text("Keyboar toolbar")
                .keyboardToolbar(height: 50) {
                    HStack {
                        TextField("Username", text: $username)
                    }
                    .border(.secondary, width: 1)
                    .padding()
                }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我相信只有在选择输入字段(键盘打开)时此工具栏才会可见。OP 正在尝试模拟 iMessage,就像聊天输入栏一样,如果没有键盘,它会粘在底部。 (3认同)

归档时间:

查看次数:

4379 次

最近记录:

4 年,5 月 前