Esowes
Esowes

Reputation: 297

SwiftUI list row layout

Back with a couple of SwiftUI layout questions :

I'm trying to display 2 lists side by side with custom cells. I created the cell views (EventRow.swift) and I display them in my content view.

I added a border to my lists, for better visibility.

As you can see from the picture below, the result is ghastly:

enter image description here

I would like the gradient effect to be applied to the whole cell, width and height wise.
I tried setting the frame of my EventRow (using .infinity for width and height), but this crashes the app.
Since the size of EventRow is inferred, I also don't know how to adapt my row cells height to its size : you can see the horizontal delimitating bars are not fitted to my custom EventRow...

If anyone has some pointers for this, it would be greatly appreciated.

The sample project can be found here

But I also post my code below:

ContentView :

import SwiftUI

struct ContentView: View {

    struct listsSetup: ViewModifier {
      func body(content: Content) -> some View {
        return content
        .frame(maxHeight: UIScreen.main.bounds.size.height/3)
        .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.blue, lineWidth: 1))
            .padding([.top, .bottom])
        }
    }

    var body: some View {

        VStack {
                HStack {
                    VStack { // 1 list Vstack
                        VStack {
                        Text("List 1")
                            .padding(.top)
                        List {
                            EventRow()
                            EventRow()
                        } // END of 1st List
                        }
                            .modifier(listsSetup())
                    } // END of 1st list VStack

                    VStack { // 2nd Vstack
                        VStack {
                        Text("List 2")
                            .padding(.top)
                        List {
                            EventRow()
                            EventRow()
                        } // END of Landings List
                        }
                        .modifier(listsSetup())
                    } // End of 2nd List VStack
                } // End of 1st & 2nd lists HStack
                    .padding(.top)
                Spacer()
        } // END of VStack
    } // END of body

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
    ContentView()
    }
}

EventRow :

import SwiftUI

struct EventRow: View {

    var body: some View {
        LinearGradient(gradient: Gradient(colors: [Color.white, Color.blue]), startPoint: .top, endPoint: .bottom)
        .edgesIgnoringSafeArea(.all)
        .overlay(
            VStack{
            HStack {
            Text("Text one")
                Spacer()
            Text("Text two")
            }
                HStack {
                    Spacer()
                    Image(systemName: "flame")
                    .font(.body)
                    Spacer()
                } // END of second HStack
                    .padding(.top, -14)
            } //END of Vstack
        )
    }
}

struct EventRow_Previews: PreviewProvider {
    static var previews: some View {
       EventRow().previewLayout(.fixed(width: 300, height: 60))

    }
}

Edit after trying Asperi's solution :
My actual EventRow code is as follows, and the listRowBackground modifier doesn't seem to have any effect :

import SwiftUI
import CoreData

struct EventRow: View {

    var event: Events

    var dateFormatter: DateFormatter {
     let formatter = DateFormatter()
    // formatter.dateStyle = .long
     formatter.dateFormat = "dd MMM yy"
     return formatter
     }

    var body: some View {
    VStack{
            HStack {
            Text(event.airportName ?? "")
                .font(.headline)
                Spacer()
            Text(self.dateFormatter.string(from: event.eventDate!))
                .font(.body)
            }
                HStack {
                    Text(event.flightNumber ?? "")
                        .font(.body)
                    Spacer()
                    if event.isSimulator {
                        Image(systemName: "s.circle")
                            .font(.body)
                    } else {
                        Image(systemName: "airplane")
                        .font(.body
                        )
                    }
                    Spacer()
                    if event.aircraftType == 0 {
                        Text("")
                        .font(.body)
                    } else if event.aircraftType == 1 {
                        Text("330")
                        .font(.body)
                    } else if event.aircraftType == 2 {
                        Text("350")
                        .font(.body)
                    }
                } // END of second HStack
                    .padding(.top, -14)

        } //END of Vstack
                .listRowBackground(LinearGradient(gradient: Gradient(colors: [Color.white, Color.blue]), startPoint: .top, endPoint: .bottom))

    }
}

struct EventRow_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

                let newEvent = Events(context: context)
                newEvent.eventDate = Date()
                newEvent.aircraftType = 1
                newEvent.airportName = "LDG tst"
                newEvent.flightNumber = "AF TEST"
                newEvent.id = UUID()
                newEvent.isLanding = true
                newEvent.isSimulator = false

        return EventRow(event: newEvent).environment(\.managedObjectContext, context)
        .previewLayout(.fixed(width: 300, height: 60))

    }
}

Upvotes: 1

Views: 2959

Answers (1)

Asperi
Asperi

Reputation: 258413

Here is a solution to make gradient row-wide

demo

struct EventRow: View {

    var body: some View {
        VStack{
            HStack {
                Text("Text one")
                Spacer()
                Text("Text two")
            }
            HStack {
                Spacer()
                Image(systemName: "flame")
                    .font(.body)
                Spacer()
            } // END of second HStack
                .padding(.top, -14)
        } //END of Vstack
        .listRowBackground(LinearGradient(gradient: Gradient(colors: [Color.white, Color.blue]), startPoint: .top, endPoint: .bottom)
        )
    }
}

Upvotes: 1

Related Questions