【问题标题】:SwiftUI List disclosure indicator without NavigationLink没有 NavigationLink 的 SwiftUI 列表披露指示器
【发布时间】:2020-09-26 01:09:13
【问题描述】:

我正在寻找一种解决方案来显示披露指示器 V 形,而无需将我的视图包装到 NavigationLink 中。例如,我想显示指示器但不导航到新视图,而是显示模式。

我找到了很多隐藏指示器按钮的解决方案,但没有一个解释如何添加一个。在当前的 SwiftUI 版本中这甚至可能吗?

struct MyList: View {
    var body: some View {
        NavigationView {
        List {
            Section {
                Text("Item 1")
                Text("Item 2")
                Text("Item 3")
                Text("Item 4")

            }
        }
    }
}

例如,我想将披露指示符添加到Item 1,而无需将其包装到NavigationLink

我已经尝试使用chevron.right SF 符号伪造指标,但该符号与默认的 iOS 符号 100% 不匹配。顶部是默认底部是chevron.right

【问题讨论】:

  • 这看起来很相似:Image(systemName: "chevron.right").font(Font.system(.footnote).weight(.semibold))
  • @pawello2222 非常感谢,看起来也和原来的一样。现在我有两个解决方案(y)

标签: swift swiftui swiftui-list swiftui-navigationlink


【解决方案1】:

希望这就是您正在寻找的。您可以将项目添加到 HStack 中,并在中间使用 Spacer 将其伪装成链接:

HStack {
                    Text("Item 1")
                    Spacer()
                    Button(action: {

                    }){
                        Image(systemName: "chevron.right")
                            .font(.body)
                    }
                }

【讨论】:

  • 非常感谢您的回答! - 我已经这样做了,不幸的是它没有 100% 解决我的问题,因为 chevron.right 与默认披露指示器的外观不匹配。我应该在我的问题中写下这个,抱歉 -> 现在编辑我的问题。
  • 您可以尝试将字体大量编辑为正确的样式。我通过这样做非常接近: .font(Font.system(size: 13, weight: .semibold, design: .default)) .foregroundColor(Color(red: 0.771, green: 0.771, blue: 0.779))
  • 哦,你是对的,我完全忘记了我可以用那种方式修改图像。在 SwiftUI 中要记住的事情太多了。谢谢,看起来真的很像原版。谢谢!
  • 如果您使用颜色.foregroundColor(Color(UIColor.tertiaryLabel)),那么它也正确支持暗模式。
【解决方案2】:

绝对有可能。

您可以使用Button 和非功能性NavigationLink 的组合来实现您想要的。

NavigationLink上添加以下扩展。

extension NavigationLink where Label == EmptyView, Destination == EmptyView {

   /// Useful in cases where a `NavigationLink` is needed but there should not be
   /// a destination. e.g. for programmatic navigation.
   static var empty: NavigationLink {
       self.init(destination: EmptyView(), label: { EmptyView() })
   }
}

然后,在您的 List 中,您可以为该行执行以下操作:

// ...
ForEach(section.items) { item in
    Button(action: {
        // your custom navigation / action goes here
    }) {
        HStack {
            Text(item.name)
            Spacer()
            NavigationLink.empty
        }
    }
 }
 // ...

以上产生的结果与您使用 NavigationLink 时的结果相同,并且还按预期在交互中突出显示/取消突出显示该行。

【讨论】:

  • 非常感谢,比起人字形符号,我更喜欢这个解决方案。唯一的缺点是这只适用于iOS 14,不适用于iOS 13。另外,需要为Text设置字体颜色,否则它会显示为蓝色。
【解决方案3】:

在 iOS15 中,以下是更好的匹配,因为其他解决方案有点太大而且不够大胆。与指定字体大小相比,它还可以更好地调整到不同的显示比例。

HStack {
    Text("Label")
    Spacer()
    Image(systemName: "chevron.forward")
      .font(Font.system(.caption).weight(.bold))
      .foregroundColor(Color(UIColor.tertiaryLabel))
}

如果有一个官方的方式来做这件事会很好。更新每个操作系统调整很烦人。

【讨论】:

    【解决方案4】:

    或者创建一个假的并使用它,即使你点击你也可以调用你的事件。

     NavigationLink(destination: EmptyView()) {
                HStack {
                    Circle()
                     Text("TITLE")  
                   
                }
            }
            .contentShape(Rectangle())
            .onTapGesture {
                print("ALERT MAYBE")
            }
    

    【讨论】:

      【解决方案5】:

      我找到了一个原始的解决方案。手动插入图标不会带来完全相同的外观。

      诀窍是使用带有“isActive”参数的初始化程序并传递一个始终为假的本地绑定。所以 NavigationLink 会等待一个永远不会发生的以编程方式触发的事件。

      // use this initializer
      NavigationLink(isActive: <Binding<Bool>>, destination: <() -> _>, label: <() -> _>)
      

      您可以将空闭包传递给目标参数。无论如何,它永远不会被调用。要执行一些操作,您可以在 ZStack 的顶部放置一个按钮。

      func navigationLinkStyle() -> some View {
          let never = Binding<Bool> { false } set: { _ in }
          return ZStack {
              NavigationLink(isActive: never, destination: { }) {
                  Text("Item 1")  // your list cell view
              }
              Button {
                 // do your action on tap gesture
              } label: {
                  EmptyView()  // invisible placeholder
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        对于可访问性,您可能需要模仿 UIKit 版本的披露指示符。 您本身不需要以这种方式实现它,但如果您使用例如用于测试的 Appium,您可能希望使用它来保持测试成功

        显然UIKit 的披露指示器是一个带有一些可访问性值的禁用按钮,所以这里是解决方案:

        struct DisclosureIndicator: View {
            var body: some View {
                Button {
        
                } label: {
                    Image(systemName: "chevron.right")
                        .font(.body)
                        .foregroundColor(Color(UIColor.tertiaryLabel))
                }
                .disabled(true)
                .accessibilityLabel(Text("chevron"))
                .accessibilityIdentifier("chevron")
                .accessibilityHidden(true)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2019-10-24
          • 1970-01-01
          • 1970-01-01
          • 2023-03-27
          • 1970-01-01
          • 2015-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多