SwiftUI中相当于UIViewController的输入附件视图,即键盘上方的视图始终可见,类似于iMessage的视图。

7

UIViewController上的简单输入附加视图

我想要一个像iMessage中看到的输入附加视图。该条在屏幕底部始终可见。当TextField获得焦点时,键盘跳入,条自动向上移动,同时固定在键盘顶部。

即使没有文本输入焦点也必须显示输入附加

在UIKit中,ViewController可以覆盖inputAccessory并成为第一个响应者。因此,输入附加视图是永久可见的。我找不到在SwiftUI中实现这一点的方法。

键盘和附件必须缩小滚动视图

当键盘弹出时,包含消息并填充整个屏幕的滚动视图必须相应缩小。当拖动ScrollView并交互式移动键盘时,也适用相同的操作。在拖动过程中必须调整视图大小。

最重要的:在拖动ScrollView并交互式移动键盘时必须正常工作

最重要的要求是,在拖动滚动视图并将键盘交互式移动时,必须平稳地运行。这与iMessage或WhatsApp中的行为相同。在拖动时,输入附加必须移动,并且滚动视图必须调整大小。在键盘消失后,工具栏/输入附加必须保持在底部可见。

不是重复的问题

我阅读了InputAccessoryView / View Pinned to Keyboard with SwiftUI,但这与我的问题不相似。我需要即使键盘未显示也能看到工具栏。而且,在该问题中接受的答案在iOS 15上无法正常工作。拖动以关闭键盘会留下白色间隙。

UIKit可行

在UIKit实现中,持有视图是UITableViewController,键盘关闭交互设置。这意味着,当键盘显示时,您可以拖动该视图,并在同一移动中将键盘和附件视图向下拖动,直到键盘消失。然而,附加视图仍然保留在底部。

在UIKit中实现很简单,如下所示。一切都可以轻松完成。

class ChatTableViewController: UITableViewController {
...

    override var inputAccessoryView: UIView? {
        return inputBar
    }

    override var canBecomeFirstResponder: Bool {
        return true
    }
...
}

UIKit实现看起来不错

UIKit实现看起来不错

需要在SwiftUI中寻求帮助(Xcode 13 beta 5,iOS 15)

对于SwiftUI,我已经发现在iOS 15中有一个placement: .keyboard 参数,可以在键盘顶部放置工具栏。但问题是,只有当TextField被聚焦时,此功能才有效。如果没有TextField被聚焦,也就是没有键盘或者键盘被关闭,那么工具栏就不可见。

struct Chat: View {
    @State private var text: String = ""
    
    var body: some View {
        ZStack {
            ScrollView {
                ScrollViewReader { value in
                    LazyVStack(spacing: 15) {
                        ForEach((1...10), id: \.self) { x in
                            let isOwner = x % 2 == 0;
                            
                            ChatMessage(isOwner: isOwner)
                                .padding(.leading, isOwner ? 90 : 0)
                                .padding(.trailing, isOwner ? 0 : 90)
                        }
                    }
                    .padding(.horizontal)
                    .padding(.top, 10)
                    .onAppear {
                        value.scrollTo(10, anchor: .bottomTrailing)
                    }
                }
            }
            .background(Color.red)
            .ignoresSafeArea(.keyboard)

            VStack {
                // Toolbar only visible if this box has focus
                TextField("", text: $text)
                    .padding(10)
                    .background(Color(.systemGray6))
                    .cornerRadius(5)
            }
        }
        .navigationBarTitle("test")
        .navigationBarTitleDisplayMode(.inline)
        .onAppear {
            UIScrollView.appearance().keyboardDismissMode = .interactive
        }
        .toolbar {
            ToolbarItemGroup(placement: .keyboard) {
                HStack {
                    TextField("", text: $text)
                        .padding(10)
                        .background(Color(.systemGray6))
                        .cornerRadius(5)

                    Text("Hello")
                }
                .padding(.vertical, 5)
                .padding(.horizontal)
                .background(Color.blue)
            }
        }
    }
}

但是如果没有对TextField进行聚焦,工具栏根本不可见

但是如果没有对TextField进行聚焦,工具栏根本不可见


@LeoDabus 请看一下我的详细信息。这不是关于将工具栏分配给视图的问题。我希望该工具栏始终可见,即使您的文本字段具有焦点。 - Tuan
我遇到了完全相同的问题,很想找到解决方案。 - alionthego
你想出了一个办法吗? - hyouuu
抱歉,仍然没有找到解决方法 :( - Tuan
1个回答

2
只要您的视图以某种方式锚定到视口底部,当虚拟键盘显示时,它应该向上移动。例如,在这里我使用一个.overlay修饰符来显示一个简单的视图,使用一个VStackSpacer()来确保视图位于容器底部:
NavigationView {
  EventForm()
    .overlay {
      VStack {
        Spacer()
        // replace the view below with your toolbar
        Text("Toolbar")
          .padding()
          .frame(maxWidth: .infinity)
          .background(Color.cyan)
      }
    }
}

工具栏悬浮在键盘上方

当键盘不出现时,默认情况下视图会避开安全区域(请注意彩色背景向下扩展的情况)。

如果您想避免这种行为,那么可以使用 .ignoresSafeArea 修饰符,但必须小心将键盘从要忽略的安全区域视图列表中排除。目前,唯一的安全区域值是 .container.keyboard,因此您可以明确指定:

.ignoresSafeArea(.container, edges: .bottom)

1
感谢您的回答。这里有两个遗漏的点。第一个是我在问题描述中没有表述清楚,所以我添加了这个细节。当键盘上移时,填充视图必须相应地缩小。第二个也是最重要的是,当滚动视图被向下拖动并且键盘被交互式移动时,也会发生调整大小。 - Tuan
我不知道什么是EventForm,但我已经尝试使用Rectangle().fill(.red)替换event form的相同代码,当键盘进入屏幕时视图不会上移。 - João Serra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接