SwiftUI List is not showing any items - swiftui

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).

Related

Does a LazyVStack remain "lazy" if it's inside a VStack?

Let's consider a list of 100 posts. According to Apple, if I layout them inside a LazyVStack:
the stack view doesn’t create items until it needs to render them
onscreen.
What if I embed that LazyVStack inside a VStack? Does it still load the views "as needed"?
struct MyView: View {
init() {
print("init...")
}
var body: some View {
Text("test")
}
}
struct ContentView: View {
var body: some View {
ScrollView {
VStack {
LazyVStack {
ForEach.init(0..<100) { int in
MyView()
}
}
}
}
}
}
Running the above code, as we scroll we can see more MyViews are init'd (by viewing the print statements in the console), so it seems like a LazyVStack in a VStack does indeed create it's content lazily. We can see the same is true when removing the VStack as well.

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.

Combining Navigation Bar, TabView and searchable causes the NavigationBar UI issue with lists

Combining Navigation Bar, TabView and searchable causes the NavigationBar and Search InputField to stay stationary when scrolling up on the second selected tab.
If I run the code below and first click on the Bookmark tab and scroll the list up, I get the desired results as shown in Figure 1.
If I immediately click the Home tab after the Bookmark tab and scroll the list up, I get an undesirable effect of the list displaying underneath the navigation header as shown in Figure 2.
The order that you click on the tabs produces different effects, and the position you last left the list before going to the next tab also has some strange influence on the behavior.
I need to use the TabView because it "remembers" the position of the list when you move from tab to tab. Creating my own tab control causes the list to reset everytime its displayed and I understand why. We also need to wrap the TabView under the NavigationView because our application subviews need to display their own tabs.
My questions, what am I doing wrong that is causing these inconsistencies in the navigation header. I have tried putting each list in it's own Stack but no joy, same issue keeps happening.
Any assistance would be greatly appreciated, we are currently blocked on our navigation design because of this anomaly. Hoping it's out fault so we can correct it.
----> the complete code <-------------------------------------------------------
struct ContentView: View {
#State var selectedTab: String = "Home"
#State var searchText: String = ""
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
ListView(itemTitle: "Home List", itemCount: 50)
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}.tag("Home")
ListView(itemTitle: "Bookmark List", itemCount: 20)
.tabItem {
Image(systemName: "bookmark.circle.fill")
Text("Bookmark")
}.tag("Bookmark")
Text("Profile Tab")
.tabItem {
Image(systemName: "person.crop.circle")
Text("Profile")
}.tag("Profile")
}
.navigationTitle(selectedTab)
}
.searchable(text: $searchText)
.onSubmit(of: .search) {
// Do something
}
}
}
struct ListView: View {
var itemTitle: String
var itemCount: Int
var body: some View {
List(){
ForEach(1...itemCount,id: \.self){ i in
NavigationLink(destination: ListViewDetailView("\(itemTitle) \(i)")) {
VStack(alignment: .leading){
Text("\(itemTitle) \(i)").padding()
}
}
}
}
}
}
struct ListViewDetailView: View {
var text:String
init(_ text: String){
self.text = text
}
var body: some View {
Text(text).navigationTitle(Text("\(text) Detail"))
}
}

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 Navigation Bar Title doesn't appear

I'm not sure if anything changed in Beta 3, however, when trying to add the NavigationBarTitle modifier to NavigationView, it does not show the text for the title? Any ideas?
NavigationView {
List(0 ..< 20) { item in
NavigationLink(destination: Text("1")) {
Text("Navigate 1")
}
}
}.navigationBarTitle(Text("Update")).navigationBarHidden(false)
}
The list shows but no title for the list in the NavigationView
You're setting .navigationBarTitle and .navigationBarHidden on NavigationView when they should be modifiers on List instead:
NavigationView {
List(0..<20) { item in
NavigationLink(destination: Text("1")) {
Text("Navigate 1")
}
}
.navigationBarTitle("Update")
.navigationBarHidden(false)
}
You can also just remove .navigationBarHidden(false) (unless you're setting it to true in a previous view or something).
Your code works fine and the navigationBarTitle is not outdated. It must be placed above (inside the Navigation View). Yes, it is sometimes confusing, it is necessary to remember this.
To the place where you currently have it .navigationBarTitle(Text ("Update")).navigationBarHidden(false) you need to set the modifier .navigationViewStyle(StackNavigationViewStyle ()), which means that you should always show the first screen regardless of the screen size.
var body: some View {
NavigationView {
List(0 ..< 20) { item in
NavigationLink(destination: Text("1")) {
Text("Navigate 1")
}
}
.navigationBarTitle(Text("Update"), displayMode: .automatic).navigationBarHidden(false)
}
// that means only show one view at a time no matter what device I'm working
.navigationViewStyle(StackNavigationViewStyle())
}