从子视图 SwiftUI 中删除 UI 元素

Posted

技术标签:

【中文标题】从子视图 SwiftUI 中删除 UI 元素【英文标题】:Removing UI Element from Child View SwiftUI 【发布时间】:2020-02-04 23:14:07 【问题描述】:

我正在尝试创建一个 SwiftUI 视图,该视图将充当我正在设计的应用程序的一种主页。作为其中的一部分,我想在主页顶部包含一个突出的搜索栏。但是,也许我对 NavigationViewTabBar 在 SwiftUI 中的工作方式有些困惑,因为当我导航到我想要的子页面时,搜索栏不会消失。这是一个展示我正在谈论的内容的 gif:

一旦我导航到特定的测试帖子,我希望搜索栏消失,但它仍然在页面顶部,而 NavigationLink 中的视图发生变化:

VStack(spacing: 0) 
    HStack(spacing: 0) 
        Image(systemName: "heart.fill")
            .padding([.leading, .bottom, .trailing], 2.0)
            .frame(width: 99, height: 99, alignment: .topLeading)
            .aspectRatio(contentMode: .fill)
        SearchBar(text: $searchTerm)
            .edgesIgnoringSafeArea(.all)
    

    // I only want all of this displayed within the parent view, the home page.

    NavigationView 
        List(categories.keys.sorted(), id: \String.self) 
            // ... create the view
        
        .navigationBarTitle(Text("SwiftUI Test"))
    
    .onAppear // do stuff 

这是在页面底部创建工具栏的代码示例,该工具栏将这个“主页”(名为 FeedView())和另一个暂时不相关的页面分开。

struct AppView: View 
    var body: some View 
        TabView 
            FeedView()
                .tabItem 
                    Image(systemName: "house.fill")
                    Text("Feed")
                
            // other pages in the navbar
        .navigationBarBackButtonHidden(true)
    

我的问题是什么?如何从所有非父页面中删除搜索栏?


编辑

在实施 Asperi 的更改后,我遇到了一个新问题。我必须创建一些新的@State@Binding 变量,以便在两个类之间传递它们的showHeader 变量,而且响应时间有点慢,并且在大约一半的时间里正确传递了更新。看看:

以及相关代码更改:(父视图)

@State private var showHeader = true

var body: some View 
    VStack(spacing: 0) 
        if showHeader 
            HStack(spacing: 0) 
                // header
            
        

        NavigationView 
            List(categories.keys.sorted(), id: \String.self) 
                key in CategoryRow(nameOfCategory: "\(key)".uppercased(), posts: self.posts[key]!, showHeader: self.$showHeader)
            
          

(子视图;一个 CategoryRow 元素):

@Binding var showHeader: Bool

// ...

NavigationLink(destination: ExpandMediaView(post: post)
    .onAppear  self.showHeader = false 
    .onDisappear  self.showHeader = true 
)

代码有时只命中 NavigationLink 的 .onDisappear 部分。为什么?

【问题讨论】:

Tabview 应该是您的顶部视图,如果您希望它显示在 FeedView 中,那么您的搜索应该在 FeedView 中。 【参考方案1】:

您的搜索栏不在导航视图中,这就是它在导航后仍然可见的原因,因为您的导航是在导航视图中执行的,而不是全屏。

所以实现目标的方法可能如下(示意性地,提供的代码不可测试)

@State private var showHeader = true // << add conditional state for header
...
VStack(spacing: 0) 
    if showHeader  // << present header conditionally
      HStack(spacing: 0) 
          Image(systemName: "heart.fill")
              .padding([.leading, .bottom, .trailing], 2.0)
              .frame(width: 99, height: 99, alignment: .topLeading)
              .aspectRatio(contentMode: .fill)
          SearchBar(text: $searchTerm)
              .edgesIgnoringSafeArea(.all)
      
    
    // I only want all of this displayed within the parent view, the home page.

    NavigationView 
        List(categories.keys.sorted(), id: \String.self) 
            // ... create the view
            NavigationLink(destination: 
               YourDestinationView()
                  .onAppear  self.showHeader = false  // << hide header
                  .onDisappear  self.showHeader = true  // << show header
            )  
              // ... label here
            
        
        .navigationBarTitle(Text("SwiftUI Test"))
    
    .onAppear // do stuff 

【讨论】:

我的 NavigationView 创建了另一组组件,然后将 NavigationLink 嵌入其中,我设法弄清楚如何在两个视图之间传递 showHeader 变量。我现在遇到的问题是showHeader 状态似乎更新得太慢,有时在视图之间传递变量时根本无法更新。我会尽快更新帖子的更改以及新动画。【参考方案2】:

只需将搜索栏放入 List

【讨论】:

以上是关于从子视图 SwiftUI 中删除 UI 元素的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从子视图传递到父视图到 SwiftUI 中的另一个子视图?

SwiftUI:从子视图中关闭模式

如何在 SwiftUI 中随时从子视图作为父视图访问数据?

如何在 Swift UI 中删除 Picker 视图的灰色背景框

计时器经过后,SwiftUI 应用程序的 UI 测试未找到设置了可访问性标识符的元素

Swift UI:使用数组中的随机元素更新视图