SwiftUI repeating TabView - swiftui

From this article, I took this code:
struct ContentView: View {
var body: some View {
TabView {
Text("First")
Text("Second")
Text("Third")
Text("Fourth")
}
.tabViewStyle(.page)
}
}
This works for a paging view, but I want it to repeat the pages so when it gets to the last item, the next scroll will get to the first item again and repeat.
Is there a SwiftUI easy way to achieve this? Any idea how to get this to work as described?

Related

How to fix double back button in SwiftUI

I got 2 views. On the second view I have list of exercises and when I choose one of them and go inside I see double back. It's driving me crazy.
First one:
import SwiftUI
struct ProgrammView: View {
var body: some View {
NavigationView{
ScrollView(.vertical, showsIndicators: false) {
VStack {
Text("blabla")
.multilineTextAlignment(.center)
.font(.custom("AvenirNext-Bold", size: 30))
NavigationLink{
InsultHandProgram()
} label: {
Image("35")
.resizable()
.scaledToFit()
.padding(.horizontal)
.padding(.bottom, 7)
.shadow(radius: 5)
}
}
}
}
}
}
Second one:
import SwiftUI
struct InsultHandProgram: View {
let numbers = InsultProgram.getInsultProgram()
var body: some View {
NavigationStack {
List(numbers) { InsultProgram in
NavigationLink( InsultProgram.name, value: InsultProgram)
}
.navigationTitle("blabla")
.navigationDestination(for: InsultProgram.self) {
InsultProgram in InsultProgrammDetail(InsultProgram: InsultProgram)
}
}
}
I tried to change navigation stack. It's crushed.
If you use NavigationView, then it provides the navigation bars for all its child views. NavigationStack in your child view also wants to provide a navigation bar, and so you end up with two.
To remedy the situation you have some choices:
Remove the NavigationStack from your child view and let NavigationView manage everything.
Remove NavigationStack from you child view and replace NavigationView in your parent with a NavigationStack. This will work fine on iPhones, but doesn't adapt well to iPads.
Keep your navigation stack in the child view but replace NavigationView with NavigationSplitView. This came in with iOS16, as did NavigationStack. The two work well together so they don't step on each other's toes when it comes to setting up navigation bars.
Given you're already using other iOS 16 idioms such as navigationDestination I'd recommend approach 3.

How SwiftUI TabView Page handles big data

I use TabView to browse albums because I need a paging function, but my album has thousands of pictures, and TabView is very slow to process.
Is there any way to lazy loading so that TabView can handle thousands of data.
TabView(selection: $assetModel.identifier) {
ForEach(0..<7000) { index in
let asset = assetModel.assetArray[index]
AssetPreviewItemView(asset: asset)
.tag(asset.localIdentifier)
}
}
.tabViewStyle(.page(indexDisplayMode: .always))
.indexViewStyle(.page(backgroundDisplayMode: .always))
At the moment (Xcode13.2.1), TabView will init all of your 7000 AssetPreviewItemView each time you change your TabView's selection (everytime you swipe images), so that's why it's so laggy.
As I've found out so far (really hope that i was wrong) the only way you can swipe through page tab view without loading everything is using #State for index only (replace your $assetModel.identifier with something like $identifier from #State var identifier).
to get rid of 7000 inits, you have to keep index as private use
struct TestTabPageView: View {
#State var index = 0
var body: some View {
VStack {
TabView(selection: $index) {
ForEach((0..<7000), id: \.self) { i in
TestTabPageViewCell(content: "\(i)").tag(i)
}
}
.tabViewStyle(.page(indexDisplayMode: .always))
}
}
}

LazyVGrid onTapGesture navigate to next screen swiftUI

I am quite new to swiftUI. I have created a grid view on tapping on which I want to go to next screen. But somehow I am not able to manage to push to next screen. I am doing like this:
var body: some View {
NavigationView {
ScrollView {
LazyVGrid(columns: gridItems, spacing: 16) {
ForEach(viewModel.pokemon) { pokemon in
PokemonCell(pokemon: pokemon, viewModel: viewModel)
.onTapGesture {
NavigationLink(destination: PokemonDetailView(pokemon: pokemon)) {
Text(pokemon.name)
}
}
}
}
}
.navigationTitle("Pokedex")
}
}
Upon doing like this, I am getting a warning stating
Result of 'NavigationLink<Label, Destination>' initializer is unused
Can someone please guide me, how to do this?
.onTapGesture adds an action to perform when the view recognizes a tap gesture. In your case you don't need to use .onTapGesture. If you want to go to another view when cell is tapped you need to write NavigationLink as below.
NavigationLink(destination: PokemonDetailView(pokemon: pokemon)) {
PokemonCell(pokemon: pokemon, viewModel: viewModel)
}
If you want to use .onTapGesture, another approach is creating #State for your tapped cell's pokemon and using NavigationLink's isActive binding. So when user tap the cell it will change the #State and toggle the isActive in .onTapGesture. You may need to add another Stack (ZStack etc.) for this.
NavigationView {
ZStack {
NavigationLink("", destination: PokemonDetailView(pokemon: pokemon), isActive: $isNavigationActive).hidden()
ScrollView {
// ...

SwiftUI: Remove Space above Navigation Bar

I have a simple view hierarchy between two views in SwiftUI.
MainView: This is the top level screen
import SwiftUI
struct MainView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: SearchView()) {
Text("Search")
}
}
.navigationBarTitle("")
.navigationBarHidden(true)
}
}
}
SearchView:
import SwiftUI
struct SearchView: View {
var body: some View {
Text("Hello, World!")
}
}
I don't want a navigation bar on my main view, but I do want a "back" button on the Search view. This is how the Search view looks:
I don't want the space above the back button - where is that coming from?
I inspected the view hierarchy and it seems the view has TWO UINavigationBar objects. If I hide the navigation bar inside the Search View, the back button goes but the space still remains.
How do I get rid of this unwanted space above the Back button?

SwiftUI List is not showing any items

I want to use NavigationView together with the ScrollView, but I am not seeing List items.
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView{
VStack {
Text("Some stuff 1")
List{
Text("one").padding()
Text("two").padding()
Text("three").padding()
}
Text("Some stuff 2")
}
}
}
}
}
All I see is the text. If I remove ScrollView I see it all, but the text is being pushed to the very bottom. I simply want to be able to add List and Views in a nice scrollable page.
The ScrollView expects dimension from content, but List expects dimension from container - as you see there is conflict, so size for list is undefined, and a result rendering engine just drop it to avoid disambiguty.
The solution is to define some size to List, depending of your needs, so ScrollView would now how to lay out it, so scroll view could scroll entire content and list could scroll internal content.
Eg.
struct ContentView: View {
#Environment(\.defaultMinListRowHeight) var minRowHeight
var body: some View {
NavigationView {
ScrollView{
VStack {
Text("Some stuff 1")
List {
Text("one").padding()
Text("two").padding()
Text("three").padding()
}.frame(minHeight: minRowHeight * 3).border(Color.red)
Text("Some stuff 2")
}
}
}
}
}
Just wanted to throw out an answer that fixed what I was seeing very similar to the original problem - I had put a Label() item ahead of my List{ ... } section, and when I deleted that Label() { } I was able to see my List content again. Possibly List is buggy with other items surrounding it (Xcode 13 Beta 5).