Is it possible to integrate a list inside of a bigger Scrollview with other elements like in the example below? In this example the list isn't shown. Is this not the intended use case of a list? Do I have do imitate this with an own container?
struct ContentView: View{
var body: some View{
ScrollViewReader{reader in
ScrollView{
VStack{
Text("List")
List(0..<10){zahl in
Text("\(zahl)")
}
}
}
}
}
}
Related
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.
This question already has an answer here:
SwiftUI iOS14 - NavigationView + List - Won't fill space
(1 answer)
Closed 2 years ago.
If I wrap a VStack with a List inside a NavigationView, the resulting list is indented, see image. This is not the expected formatting because I'd want the list to cover the whole screen width.
How can I fix this and why does this happen?
Note: This indentation behavior would go away if I remove the VStack, but here I do want to include the Text box ("Something...") inside the NavigationView, because I want it to go away once a user clicks on an item.
Full code below, Xcode 12.3:
import SwiftUI
struct ListView: View {
var items: [String]
var body :some View {
List {
ForEach(items, id: \.self) { item in
NavigationLink(destination: Text(item)){
Text(item)
}
}
}
}
}
struct ContentView: View {
var body: some View {
NavigationView{
VStack{
Text("Something that should disappear when I click on the item")
ListView(items: ["a", "b"])
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Hey all you need to do is add the modifier for a .liststyle
.listStyle(InsetListStyle())
Also you should be aware that there is no way to remove the chevron symbol on lists
import SwiftUI
struct ListView: View {
var items: [String]
var body :some View {
List {
ForEach(items, id: \.self) { item in
NavigationLink(destination: Text(item)){
Text(item)
}
}
}.listStyle(InsetListStyle())
}
}
struct ContentView: View {
var body: some View {
NavigationView{
VStack{
Text("Something that should disappear when I click on the item")
ListView(items: ["a", "b"])
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
When I embed a List grouped into Sections into a NavigationView the section headers become collapsible. I'd like to keep them non-collapsible, just like when the List is not embedded into the NavigationView.
My current code (with the NavigationView):
import SwiftUI
struct MyGroup {
var name:String, items:[String]
}
struct ContentView: View {
var groups : [MyGroup] = [
.init(name: "Animals", items: ["π","π©","π","π","π","π¦©","πΏ","π"]),
.init(name: "Vehicles", items: ["π","π","π","π","π","π€","π₯","β΅οΈ"])]
var body: some View {
NavigationView {
VStack {
List {
ForEach(groups, id: \.self.name) { group in
Section(header: Text(group.name)) {
ForEach(group.items, id:\.self) { item in
Text(item)
}
}
}
}
}.navigationTitle("collections")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
It is default style applied, you can make it explicitly set for List like below (tested with Xcode 12 / iOS 14)
List {
ForEach(groups, id: \.self.name) { group in
Section(header: Text(group.name)) {
ForEach(group.items, id:\.self) { item in
Text(item)
}
}
}
}.listStyle(InsetGroupedListStyle()) // or GroupedListStyle
Just using the SidebarListStyle in listStyle modifier
.listStyle(SidebarListStyle())
In case you're stumbling on this... The issue doesn't have anything to do with being embedded in a NavigationView as the OP and #Danial mentioned. It's because it's embedded in the the VStack at the first level of the NavigationView in the example code. Seems like a SwiftUI bug to me.
I'm at a complete loss for why a List I'm trying to create (with a ForEach) in SwiftUI is behaving the way that it is. I have an ObservedObject that I verified in the inspector has the data that I'm expecting. In the first VStack, I can create the List with the ForEach and it outputs just fine. In the second VStack, I get no data output.
struct WorkoutPreview: View {
#Environment(\.managedObjectContext) var managedObjectContext
#ObservedObject var workoutSessionExercises: WorkoutSessionExercises
var body: some View {
NavigationView {
VStack {
Text("Welcome to your workout! Below are the exercises and bands you've selected for each.")
.padding()
Text("We found \(workoutSessionExercises.workoutExercises.count) workouts.")
.padding()
// This List (with ForEach) works fine and produces output.
List {
ForEach(0..<workoutSessionExercises.workoutExercises.count) { index in
Text(self.workoutSessionExercises.workoutExercises[index].exerciseName)
}
}
}
// The exact same List (with ForEach) in this VStack produces no results.
VStack {
List {
ForEach(0..<workoutSessionExercises.workoutExercises.count) { index in
Text(self.workoutSessionExercises.workoutExercises[index].exerciseName)
}
}
}
Spacer()
}
}
}
the problem is you have 2 VStacks that are not one below the other in the View, and so you can't see the second list.
To fix your problem wrap your VStacks in another VStack, such as:
var body: some View {
NavigationView {
VStack { // <------
VStack {
Text("Welcome to your workout! Below are the exercises and bands you've selected for each.").padding()
Text("We found \(workoutSessionExercises.workoutExercises.count) workouts.").padding()
// This List (with ForEach) works fine and produces output.
List {
ForEach(0..<workoutSessionExercises.workoutExercises.count) { index in
Text(self.workoutSessionExercises.workoutExercises[index].exerciseName)
}
}
}
// The exact same List (with ForEach) in this VStack produces no results.
VStack {
List {
ForEach(0..<workoutSessionExercises.workoutExercises.count) { index in
Text(self.workoutSessionExercises.workoutExercises[index].exerciseName)
}
}
}
Spacer()
} // <------
}
}
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).