将包含链接作为变量的 SwiftUI 2.0 ReusableView

Posted

技术标签:

【中文标题】将包含链接作为变量的 SwiftUI 2.0 ReusableView【英文标题】:SwiftUI 2.0 ReusableView that will contain a link as a variable 【发布时间】:2021-02-07 16:03:55 【问题描述】:

我正在开发一个包含运动列表的应用程序,我为运动的名称和图像构建了一个可重复使用的视图,用于列出每项运动。然后,当用户从运动列表中点击运动图像时,我为要打开的每项运动创建了一个视图,我为图像、运动名称和链接创建了一个变量,我不知道如何将变量与 NavigationLink 链接。我在这里迷路了,任何帮助将不胜感激。下面是我的代码。

struct SportTypeInsetView: View 
var buttonImage1: String
var buttonName1: String
var buttonLink1: String
var body: some View 
VStack 
NavigationView 
VStack 
  Button (action: 
                        
) 
  Image(buttonImage1)
   .resizable()
   .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
    
     .frame(width: 50, height: 30)
                
    Text(buttonName1)
    .font(.footnote)
    .foregroundColor(.primary)
    .multilineTextAlignment(.leading)
     .lineLimit(1)
       
      
    
    

SportTypeInsetView(buttonImage1: "Yoga-icon", buttonName1: "Yoga",buttonLink1: )

点击按钮时如何将其连接到 YogaView()?

谢谢。

【问题讨论】:

【参考方案1】:

您可以将 NavigationLink 与按钮样式 DefaultButtonStyle 一起使用。

NavigationLink 有一个 label 参数,它基本上是一个 SwiftUI 视图对象,你可以简单地传递一个 Text 对象使其看起来像按钮或同时传递 ImageText,这取决于你,最终结果将是按钮样式NavigationLink

提供按钮样式有助于为您提供类似按钮的感觉。

NavigationLink(destination: SportDetailView(),
               label: 
                        Text("Navigate To next Screen")
             ).buttonStyle(DefaultButtonStyle())

如果你想自定义 NavigationLink 标签视图,你可以这样做。

  NavigationLink(destination: SportDetailView(),
                 label: 
                           HStack 
                               Image(systemName: "pencil")
                               Text("Edit name")
                           
               ).buttonStyle(DefaultButtonStyle())

要实现行为动态的导航链接,SportTypeInsetView 可以具有受View 协议约束的通用类型TargetView

话虽如此,您不需要buttonLink1,因为targetView 本身是动态的。

ex: 
SportTypeInsetView(targetView: YogaView(), buttonImage1: "Tap", buttonName1: "Button A", buttonLink1: "")

ex:
SportTypeInsetView(targetView: SomeAnotherSportView(), buttonImage1: "Tap", buttonName1: "Button B", buttonLink1: "")
struct SportTypeInsetView<TargetView: View>: View 

    let targetView: TargetView
    var buttonImage1: String
    var buttonName1: String
    var buttonLink1: String
    
    var body: some View 
        VStack 
            NavigationView 
                VStack 
                    NavigationLink(
                        destination: self.targetView,
                        label: 
                            //Add Image , text or button here
                            Text("Navigation to next")
                        ).buttonStyle(DefaultButtonStyle())
                    
                    
                    Text(buttonName1)
                        .font(.footnote)
                        .foregroundColor(.secondary)
                        .multilineTextAlignment(.leading)
                        .lineLimit(1)
                
            
        
    

【讨论】:

感谢一百万 @NNikN 你的回答解决了我的问题【参考方案2】:

最简单的方法是将您的Button 替换为NavigationLink。在NavigationLink 中,您向它传递一个视图 (YogaView),您可以像任何其他视图一样为其提供参数。这是一个例子:

struct ContentView : View 
    var body: some View 
        SportTypeInsetView(buttonImage1: "0", buttonName1: "Button", buttonLink1: "Link")
    


struct SportTypeInsetView: View 
    var buttonImage1: String
    var buttonName1: String
    var buttonLink1: String
    
    var body: some View 
        VStack 
            NavigationView 
                VStack 
                    NavigationLink(destination: YogaView(linkName: buttonLink1)) 
                        Image(buttonImage1)
                            .resizable()
                            .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                            .frame(width: 50, height: 30)
                    
                    
                    Text(buttonName1)
                        .font(.footnote)
                        .foregroundColor(.primary)
                        .multilineTextAlignment(.leading)
                        .lineLimit(1)
                
            
        
    


struct YogaView : View 
    var linkName : String
    
    var body: some View 
        Text(linkName)
    

如果您真的想通过按钮来实现,可以使用NavigationLinkisActive 属性和@State 变量来实现:

struct SportTypeInsetView: View 
    var buttonImage1: String
    var buttonName1: String
    var buttonLink1: String
    
    @State private var linkActive = false
    
    var body: some View 
        VStack 
            NavigationView 
                VStack 
                    Button(action:  linkActive = true ) 
                        Image(buttonImage1)
                            .resizable()
                            .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                            .frame(width: 50, height: 30)
                    
                    .overlay(
                        NavigationLink(destination: YogaView(linkName: buttonLink1), isActive: $linkActive) 
                            EmptyView()
                        )
                    
                    Text(buttonName1)
                        .font(.footnote)
                        .foregroundColor(.primary)
                        .multilineTextAlignment(.leading)
                        .lineLimit(1)
                
            
        
    

【讨论】:

感谢您的回答@jnpdx,它为我提供了解决另一个问题的方法。

以上是关于将包含链接作为变量的 SwiftUI 2.0 ReusableView的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI 2.0如何更改表单部分的背景颜色[重复]

线程可以作为另一个用户执行吗? (.NET 2.0/3.5)

SwiftUI 如何创建一个将项目添加到包含导航链接的列表的按钮

如何使用 SwiftUI 将变量传递给 MFMailComposeViewController()?

SwiftUI 2.0列表项层级缩进显示CoreData托管数据的3种实现

SwiftUI 2.0列表项层级缩进显示CoreData托管数据的3种实现