SwiftUI iterating List not applying listRow modifiers - swiftui

I have created the following List
List {
Text("Hello")
.listRowBackground(Color.red)
}
Which renders this view:
When I change the List to iterate over a range, it stops applying the listRow modifier:
List (0 ..< 3) { _ in
Text("Hello")
.listRowBackground(Color.red)
}
Why is that happening?

You required ForEach. As mention in doc
The SwiftUI ForEach structure computes views for each element of the enumeration and extracts the raw value of each of its elements using the resulting text to create each list row item. The listRowBackground(_:) modifier then places the view you supply behind each of the list row items:
So the final code is,
List {
ForEach(0 ..< 3){ _ in
Text("Hello")
.listRowBackground(Color.red)
}
}

Related

List animations ignoring Animation parameter

I've been trying to get changes to my list elements to animate correctly. However, items in a list don't seem to animate as specified.
In this simple example, an element is removed. There is an animation, within 1 second the element is removed. However, it completely ignores the duration and delay.
struct ContentView: View {
#State var items = [1, 2, 3, 4, 5]
var body: some View {
VStack {
List {
ForEach(items, id: \.self) { item in
Text("Item \(item)")
}
}
Button {
withAnimation(Animation.easeInOut(duration: 5).delay(1)) {
print("removing element")
items.removeFirst()
}
} label: {
Text("Remove element")
}
}
}
}
If I remove the List and just have a VStack of items, the Animation parameter is processed correctly.
If I remove the withAnimation, it doesn't animate at all. So it is triggering it.
I would say that this is expected as this is how underlying UITableViewController is working, it doesn't have capabilities to customise animations that way.
I think that if you want to do something custom you need to start with LazyVStack in ScrollView, that will give you more space for creation and it is quite likely that this would work (I haven't tried it, but from the logical point it should).

How do I set the selected row background color in a SwiftUI List?

I am using a standard List in SwiftUI and would like to modify the selected rows' background color.
Here is the code:
...
List {
ForEach(recipesToShow, id: \.self) { recipe in
NavigationLink(destination: RecipeDetailWrapper(recipe: recipe)) {
RecipeListRow(recipe: recipe)
.environmentObject(recipeDateFormatter)
}
}
.onDelete(perform: deleteRecipe)
} //: LIST
.listStyle(PlainListStyle())
...
This is how it looks by default:
you can use the modifier .listRowBackground(Color.blue) to modify the background color of your list.
For the specific item, I would add a state var to store the id of the element tapped and then evaluate it in each item of the list,
you can check the answer here:
How do you change the select color of a navigation link in a list
that I think is what you need.

List view in SwiftUI takes up entire screen height

In SwiftUI, list view by default takes up entire height of the screen and pushes other elements/views to the bottom of the screen. But I want to append some elements/views where the list items exactly end.
You can add spacer() at appropriate places in the VStack or try something like below:
VStack {
CustomView1()
List {
Section(header: HeaderView(), footer: FooterView())
{
ForEach(viewModel.permissions) { permission in
CustomeView2()
}
GeneralView()//add the views at the end of list items
}
}.listStyle(GroupedListStyle())
}

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

How to make two Lists in one View scroll as one page in SwiftUI?

I'm trying to add two tables with different sizes to one view in SwiftUI. I want both tables be fully expanded and the whole view to scroll as one. For now I only get both tables fixed size and scroll separately.
some View {
VStack {
Text("Table foo")
List(foo { item in Text(item.name) })
Text("Table bar")
List(bar { item in Text(item.name) })
}
}
Tried changing VStack to a ScrollView, it makes things even worse - tables are becoming one liners.
Also tried replacing List() with ForEach() but then I lose features of the List() I actually want.
I think you want one List with multiple ForEach's. Optionally, you could make it a grouped List with multiple sections. Adapted for your sample, the following concept has worked well for me on several occasions:
struct SwiftUIView: View {
var body: some View {
List {
Section(header: Text("Table foo"))
{
ForEach(foo) { item in Text(item.name) }
}
Section(header: Text("Table bar"))
{
ForEach(bar) { item in Text(item.name) }
}
}
.listStyle(GroupedListStyle())
}
}
You can use Form to embed two lists in a scroll view.
Reference: https://developer.apple.com/documentation/swiftui/form .