TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: ScrollView category title

Forums > SwiftUI

@00jim  

Similar in behaviour to the navigationTitle, I woul like the category names e.g. "Data #1" to remain at the top of the screen, untul the next category in the ScrollView meets to replace it (similar to the date label grouping chat messages in WhatsApp will change as the next group scrolls up).

import SwiftUI

let dataSet: [Data] = [

    // DATA #1
    Data(info: "Info #1A", category: .data1),
    Data(info: "Info #1B", category: .data1),
    Data(info: "Info #1C", category: .data1),
    Data(info: "Info #1D", category: .data1),
    Data(info: "Info #1E", category: .data1),
    Data(info: "Info #1F", category: .data1),

    // DATA #2
    Data(info: "Info #2A", category: .data2),
    Data(info: "Info #2B", category: .data2),
    Data(info: "Info #2C", category: .data2),
    Data(info: "Info #2D", category: .data2),
    Data(info: "Info #2E", category: .data2),
    Data(info: "Info #2F", category: .data2),

    // DATA #3
    Data(info: "Info #3A", category: .data3),
    Data(info: "Info #3B", category: .data3),
    Data(info: "Info #3C", category: .data3),
    Data(info: "Info #3D", category: .data3),
    Data(info: "Info #3E", category: .data3),
    Data(info: "Info #3F", category: .data3),

    // DATA #4
    Data(info: "Info #4A", category: .data4),
    Data(info: "Info #4B", category: .data4),
    Data(info: "Info #4C", category: .data4),
    Data(info: "Info #4D", category: .data4),
    Data(info: "Info #4E", category: .data4),
    Data(info: "Info #4F", category: .data4),

    // DATA #5
    Data(info: "Info #5A", category: .data5),
    Data(info: "Info #5B", category: .data5),
    Data(info: "Info #5C", category: .data5),
    Data(info: "Info #5D", category: .data5),
    Data(info: "Info #5E", category: .data5),
    Data(info: "Info #5F", category: .data5),
]

enum DataCategory: String, CaseIterable {
    case data1 = "Data #1"
    case data2 = "Data #2"
    case data3 = "Data #3"
    case data4 = "Data #4"
    case data5 = "Data #5"
}

struct Data: Identifiable {
    let id = UUID()
    let info: String
    let category: DataCategory
}

struct TileTitleTestView: View {

    var body: some View {
        VStack {
            Text("default")
                .padding()
                .cornerRadius(8)
        }
        .frame(maxWidth: .infinity)
        .background(Color.blue)
        .foregroundColor(.white)
        .cornerRadius(15)
        .padding(5)
    }
}

struct TileArrayView: View {
    let data: [Data]

    var body: some View {
        ScrollView {
            LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 10), count: 3), spacing: 10) {
                ForEach(DataCategory.allCases, id: \.self) { category in
                    Section(header:
                                Text(category.rawValue)
                                    .font(.system(size: 30).bold())
                                    .multilineTextAlignment(.leading)
                                    .foregroundColor(.black)
                    ) {
                        ForEach(data.filter { $0.category == category }) { data in
                            DataTile(data: data)
                                .aspectRatio(1, contentMode: .fit)
                        }
                    }
                }
            }
            .padding()
        }
    }
}

struct DataTile: View {
    let data: Data

    var body: some View {
        VStack {
            Text(data.info)
                .padding()
                .cornerRadius(8)
        }
        .frame(maxWidth: .infinity)
        .background(Color.pink)
        .foregroundColor(.black)
        .cornerRadius(15)
        .padding(5)
    }
}

As close as possible to the default behaviour of the navigationTitle, that will appear in the top centre title bar would be my goal.

1      

Use this init for LazyVGrid instead with pinnedViews:

LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 10), count: 3), spacing: 10, pinnedViews: .sectionHeaders)

is this what you are trying to achieve?

2      

@00jim  

Yes !

However, I would preffer the text to be backed by a white margin at the top, so the cells do not touch the title.

How do I achieve this please ?

1      

As possible solution change your section header to this.

Section(header:
            Color.white
    .frame(height: 60)
    .overlay {
        Text(category.rawValue)
            .font(.system(size: 30).bold())
            .multilineTextAlignment(.leading)
            .foregroundColor(.black)
    }
)

2      

@00jim  

Thank you very much once again !

This helps a lot with the effect: .statusBar(hidden: true)

1      

Great to hear you solved it! If you have any further questions or need assistance with anything else, feel free to ask!

   

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.