SwiftUI:在关闭 sheet 后,导航栏按钮的点击目标未对齐

14

我注意到在 SwiftUI 在iOS 13.3.1及更早版本中存在一些奇怪的可能是错误的行为。为了演示这种情况,以下是一个非常简单的场景:

完整的示例代码:

import SwiftUI

struct ContentView: View {
    @State var showingSheet: Bool = false
    var body: some View {
        NavigationView {
            Text("ParentView")
                .navigationBarItems(trailing: Button(action: { self.showingSheet = true }) { Text("Show") })
        }.sheet(isPresented: $showingSheet) { SheetView() }
    }
}

struct SheetView: View {
    @Environment(\.presentationMode) var presentationMode
    var body: some View {
        VStack {
            Text("Sheet content")
            Button(action: { self.presentationMode.wrappedValue.dismiss() }) { Text("Hide") }
        }
    }
}

如何重现问题:

  1. 在iOS 13.4.1上启动应用程序
  2. 点击“Show”按钮
  3. (预期中,底部弹出一个面板)
  4. 使用“Hide”按钮关闭面板
  5. (预期中,面板被关闭了)
  6. 再次点击“Show”按钮以显示面板

预期结果:面板再次显示。

实际结果:“Show”按钮的触摸目标向下偏移了几个像素,导致该操作无法触发。这可以在View层次结构调试器中观察到:

Misaligned Views

其他注意事项:

  • 如果将面板拖到屏幕底部,这种情况不会发生
  • 仅当为托管视图激活大型导航栏项目标题时,此问题才会发生,使用内联标题时没有问题

所以现在我在猜想:是我犯了错误,还是这是一个真正的SwiftUI bug?如果是,则是否有易于解决的解决方法?我在SO上搜索了类似的问题,但没有找到完全相同的问题。

编辑: 我同时向苹果提交了Radar反馈FB7560960。

编辑2: 仍然存在于13.4.1中。


当我使用UIKit的方式呈现和解散UIViewController时,我遇到了同样的问题。(iOS 15.2)为了解决这个问题,我在解散视图控制器后仅仅1毫秒就移除了工具栏按钮。虽然不太美观,有时候在解散时工具栏按钮会闪烁,但总比没有好,我想... - Manabu Nakazawa
我还在使用Xcode 14.2和iOS 16.2,仍然遇到了这个问题。对我有效的唯一解决方案是将模态呈现为全屏。这似乎也是相同的问题:https://dev59.com/ALnoa4cB1Zd3GeqPS5G3 - mluisbrown
5个回答

2

我曾经遇到完全相同的问题,但有趣的是,只有在运行iOS 14.4和15.0的某些模拟器/设备上才能重现该问题,而在iOS 13.3上则无法重现。

唯一解决该问题的变通方法是将演示模式从.automatic(即iOS >=13中的.pageSheet)更改为.fullScreen(先前的默认设置)。我想,在纯SwiftUI中,相应的解决方法应该是使用.fullScreenCover代替.sheet


2
我不知道为什么,但是在contentView中添加@Environment(\.presentationMode) var presentationMode似乎可以解决它。

确实!似乎在关闭模态窗口时会触发 ContentView 的重新渲染,顺便修复了这个错误。在我看来更像是一种解决方法而不是解决方案,但它起到了作用!谢谢。 - Joshua
似乎对我没有起作用。您所说的“contentView”是指“ContentView”吗?这是在创建新的SwiftUI项目时生成的结构,它作为应用程序的初始视图。 - Benzy

1

iOS 16+

.sheet(isPresented: $showingSheet) {
  SheetView()
   .presentationDetents([.fraction(0.999)])
 }

基本上禁用演示凸轮可以防止按钮错位。这个方法很有效!如果苹果公司能够修复这个存在多年的错误,那么这个方法就不再需要了。 - Steve Dugan

0
如果对其他人有帮助的话,我想说我在 Xcode 14.2 和 iOS 16.2 中仍然遇到了这个问题。我发现当进入和离开视图上的文本字段时,按钮的点击目标会神奇地自我修复。所以在模态窗口关闭后,我尝试了一下这种方法:
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

......它能够工作。这是一个有点巨大的hack,但这是我找到的唯一解决问题的方法。


0

我曾经遇到同样的问题,这是我摆脱它的方法。 当我的应用程序进入后台时,我关闭了表视图。 这不是最好的解决方案,但它允许我保持滑动手势。

.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
               
               showingSheet = false

           }

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