如何在NavigationView中删除Navbar

发布于 2025-01-20 02:03:11 字数 4618 浏览 4 评论 0 原文

我已经在此处询问当我从API中获取数据时,使用页面样式tabview 时如何摆脱范围索引错误。我建议这样做:

如果rockets.isempty 子句,

整个 tabview 并显示 如果数组为空(例如加载指示灯)

// MARK: - API
class InfoApi {
    func getRockets(completion: @escaping ([RocketInfo]) -> ()) {
        guard let url = URL(string: "https://api.spacexdata.com/v4/rockets") else {
            return
        }
        
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                let rocketsInfo = try JSONDecoder().decode([RocketInfo].self, from: data!)
                DispatchQueue.main.async {
                    completion(rocketsInfo)
                }
            } catch {
                print(error.localizedDescription)
            }
        }
        .resume()
    }
}

// MARK: - ROCKET MODEL
struct RocketInfo: Codable, Identifiable {
    let id = UUID()
    let name: String
    let country: String
}

// MARK: - CONTENT VIEW
struct ContentView: View {
    @State var rockets: [RocketInfo] = []
    
    var body: some View {
        Group {
            if rockets.isEmpty {
                ProgressView()
            } else {
                NavigationView {
                    TabView {
                        ForEach(rockets) { rocket in
                            ScrollView(.vertical, showsIndicators: false) {
                                VStack(alignment: .center) {
                                    Image(systemName: "globe")
                                        .renderingMode(.original)
                                        .resizable()
                                        .scaledToFit()
                                        .frame(height: 190, alignment: .center)
                                    
                                    ZStack {
                                        RoundedRectangle(cornerRadius: 32)
                                            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 865, maxHeight: .infinity, alignment: .center)
                                            .foregroundColor(Color.gray)
                                        
                                        VStack(spacing: 40) {
                                            HStack {
                                                Text("Name")
                                                    .font(.title)
                                                Spacer()
                                                Text(rocket.name)
                                                    .font(.title)
                                            }
                                        } //: VSTACK
                                        .padding(.horizontal)
                                    } //: ZSTACK
                                } //: VSTACK
                                .navigationBarTitleDisplayMode(.inline)
                                .navigationBarHidden(true)
                            } //: SCROLL
                        } //: LOOP
                    } //: TAB
                    .tabViewStyle(.page)
                    .edgesIgnoringSafeArea(.vertical)
                } //: NAVIGATION
            }
        } //: GROUP
        .onAppear {
            InfoApi().getRockets { rockets in
                self.rockets = rockets
            }
        }
        .edgesIgnoringSafeArea(.vertical)
    }
}

// MARK: - PREVIEW
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

有所帮助,但是还有另一个问题。要在 if-else 子句中包装TabView,我必须在其外部添加其他视图(例如, navigationView ),并致电 onappear 这种观点使一切正常的方法。我无法完全删除 NavigationView 顶部的白色安全区域的事实存在问题。

这就是模拟器中的外观

如果我包裹 tabview hstack 而不是 navigationView ,然后在将scrollview滚动到末端时,我看到了一个白色的条,我也不知道该如何摆脱。

我在谈论的scrollview底部的这个白色空间我在谈论

I've already asked here how to get rid of an out of range index error when using page styled TabView when I get data from API. There I was advised to do this:

Add an if rockets.isEmpty clause around the entire TabView and display
something else if the array is empty (like a loading indicator)

// MARK: - API
class InfoApi {
    func getRockets(completion: @escaping ([RocketInfo]) -> ()) {
        guard let url = URL(string: "https://api.spacexdata.com/v4/rockets") else {
            return
        }
        
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            do {
                let rocketsInfo = try JSONDecoder().decode([RocketInfo].self, from: data!)
                DispatchQueue.main.async {
                    completion(rocketsInfo)
                }
            } catch {
                print(error.localizedDescription)
            }
        }
        .resume()
    }
}

// MARK: - ROCKET MODEL
struct RocketInfo: Codable, Identifiable {
    let id = UUID()
    let name: String
    let country: String
}

// MARK: - CONTENT VIEW
struct ContentView: View {
    @State var rockets: [RocketInfo] = []
    
    var body: some View {
        Group {
            if rockets.isEmpty {
                ProgressView()
            } else {
                NavigationView {
                    TabView {
                        ForEach(rockets) { rocket in
                            ScrollView(.vertical, showsIndicators: false) {
                                VStack(alignment: .center) {
                                    Image(systemName: "globe")
                                        .renderingMode(.original)
                                        .resizable()
                                        .scaledToFit()
                                        .frame(height: 190, alignment: .center)
                                    
                                    ZStack {
                                        RoundedRectangle(cornerRadius: 32)
                                            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 865, maxHeight: .infinity, alignment: .center)
                                            .foregroundColor(Color.gray)
                                        
                                        VStack(spacing: 40) {
                                            HStack {
                                                Text("Name")
                                                    .font(.title)
                                                Spacer()
                                                Text(rocket.name)
                                                    .font(.title)
                                            }
                                        } //: VSTACK
                                        .padding(.horizontal)
                                    } //: ZSTACK
                                } //: VSTACK
                                .navigationBarTitleDisplayMode(.inline)
                                .navigationBarHidden(true)
                            } //: SCROLL
                        } //: LOOP
                    } //: TAB
                    .tabViewStyle(.page)
                    .edgesIgnoringSafeArea(.vertical)
                } //: NAVIGATION
            }
        } //: GROUP
        .onAppear {
            InfoApi().getRockets { rockets in
                self.rockets = rockets
            }
        }
        .edgesIgnoringSafeArea(.vertical)
    }
}

// MARK: - PREVIEW
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

It helped, but there was another problem. To wrap TabView in an if-else clause, I had to add some other View outside it (for example, NavigationView) and call the onAppear method for this View to make everything work. There was a problem with the fact that I cannot completely remove the white safe area at the top of NavigationView.

That's what it looks like in the Simulator

If I wrap TabView in HStack instead of NavigationView, then when scrolling ScrollView to the end, I see a white bar at the very bottom, which I also don't know how to get rid of.

This white space at the bottom of the ScrollView I was talking about

The View that I want to create

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

抚你发端 2025-01-27 02:03:11

有许多潜在的解决方案。所有这些都涉及摆脱 navigationView ,因为似乎您唯一使用的是您需要某种包装器视图。

解决方案#1:
移动 isempty TabView

var body: some View {
  TabView {
    if rockets.isEmpty {
      //ProgressView
    } else {
      //your tabs
    }
  }.onAppear {
    //API call
  }
}

解决方案> 2:2:
而不是 NavigationView ,将您的内容包装在 group

var body: some View {
  Group {
    if !rockets.isEmpty {
      TabView { /*...*/ }
    }
  }.onAppear {
    //API call
  }
}

解决方案#3:call onappear 出现时

if rockets.isEmpty {
  ProgressView()
   .onAppear {
     //API call
   }
} else {
  TabView {
    //tab content
  }
}

,模拟对象/API

struct TabBarView: View {
    @State var rockets: [RocketInfo] = []
    
    var body: some View {
        Group {
            if rockets.isEmpty {
                ProgressView()
            } else {
                NavigationView {
                    TabView {
                        
                        ForEach(rockets) { rocket in
                            Text(rocket.title)
                        }
                        
                    }
                    .tabViewStyle(.page)
                }
            }
        }
        .onAppear {
            InfoApi().getRockets { rockets in
                self.rockets = rockets
            }
        }
    }
}

There are a number of potential solutions to this. All involve getting rid of the NavigationView since it seems that your only use for it was that you needed some sort of wrapper view.

Solution #1:
Move your isEmpty check inside the TabView

var body: some View {
  TabView {
    if rockets.isEmpty {
      //ProgressView
    } else {
      //your tabs
    }
  }.onAppear {
    //API call
  }
}

Solution #2:
Instead of NavigationView, wrap your content in a Group:

var body: some View {
  Group {
    if !rockets.isEmpty {
      TabView { /*...*/ }
    }
  }.onAppear {
    //API call
  }
}

Solution #3: call onAppear on the progress view when it appears

if rockets.isEmpty {
  ProgressView()
   .onAppear {
     //API call
   }
} else {
  TabView {
    //tab content
  }
}

Edit: complete example with mocked objects/API

struct TabBarView: View {
    @State var rockets: [RocketInfo] = []
    
    var body: some View {
        Group {
            if rockets.isEmpty {
                ProgressView()
            } else {
                NavigationView {
                    TabView {
                        
                        ForEach(rockets) { rocket in
                            Text(rocket.title)
                        }
                        
                    }
                    .tabViewStyle(.page)
                }
            }
        }
        .onAppear {
            InfoApi().getRockets { rockets in
                self.rockets = rockets
            }
        }
    }
}
心欲静而疯不止 2025-01-27 02:03:11

不幸的是,事实证明,如果您在一个视图中同时使用 TabBar 和 NavigationView,则完全不可能摆脱导航栏。

Unfortunately, it turned out that it is quite impossible to get rid of navbar if you use both TabBar and NavigationView in one View.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文