cyber-bot
cyber-bot

Reputation: 547

How to make sticky bar in SwiftUI?

I'm novice in SwiftUI and still can't understand how to make sticky bar on the top of the List. Like letters in apple music app when you listing artists or songs (look example).

I explored abilities of the List and NavigationView, but got nothing. 😔

Upvotes: 11

Views: 17943

Answers (6)

Mamoon Yameen
Mamoon Yameen

Reputation: 389

SwiftUI How to make sticky Header View or header stay on the top of each Section/cell in List.

Steps:

  1. 1- Add Scroll View

    2- Use forEach in scroll view

    3- Use LazyVStack inside forEach and add pinnedView as section header in LazyVStack

    4- Inside LazyVStack use Section with header

Sample Code:

@State var headerTitleArray = ["28 Jun, 15:00","29 July, 15:00","30 Aug, 15:00","31 Sep, 15:00","1 Oct, 15:00"]

For Example we have this array of header titles in it.

ScrollView {
    ForEach(0..<headerTitleArray.count, id: \.self) { listIndex in
    
        LazyVStack(alignment: .leading, spacing: 0, pinnedViews: [.sectionHeaders]) {

            Section {
                ForEach(0..<10, id: \.self) { landmark in
                //MARK: - Items in per section
                    Text("section items")
                }
            
            } header: {

                //MARK: - Seaction header title

                Text("\(headerTitleArray(listIndex))")
                .font(AppFont(size: 18,type: "Medium"))
                .foregroundColor(AppColors.labelColor)
                .padding(.vertical,12)
                .padding(.horizontal,16)
        }
    }
}//foreach } //scrollView

This image indicates in steps that when you scroll the header stays on the top of list until next header comes to current header place

Upvotes: 2

user21453657
user21453657

Reputation:

This is easier way to use Sticky Header try this approach and let me know is it working...

    struct LatestMagazineView: View {
    @Environment(\.dismiss) var dismiss
    let columns = [GridItem(.flexible()),GridItem(.flexible())]
    @State  var searchText: String = ""
    var body: some View {
        
        ZStack {
            VStack(spacing:0) {
                Color.orange.ignoresSafeArea().frame(height: 25)
                ScrollView{
                    VStack(spacing: 0){
                        
                        AsyncImage(url: URL(string: "")){img in
                            img.resizable().frame(height: 225)
                            
                        }placeholder: {
                            Image("Anoop").resizable().frame(height: 225)
                        }
                        Image("soft").resizable().frame(width: UIScreen.main.bounds.width, height: 65, alignment: .leading)
                        
                        
                        LazyVGrid(columns: columns, spacing: 10, pinnedViews: [.sectionHeaders]){
                            Section(header:
                                        VStack{
                                TextField("Enter Search Text...", text: $searchText).font(.title)
                                
                                    .padding(4)
                                    .padding(.leading,searchText.isEmpty ? 29 : 4)
                                
                                    .foregroundColor(.white)
                                
                                    .cornerRadius(8)
                                    .overlay(
                                        RoundedRectangle(cornerRadius: 22)
                                            .stroke(Color.white, lineWidth: 2)
                                    )}.padding(6).background(Color.yellow)
                            ) {
                                ForEach(0..<21){_ in
                                    VStack(alignment: .leading){
                                        AsyncImage(url: URL(string: "")){ img in
                                            img .resizable()
                                                .frame(height: 255)
                                        }placeholder: {
                                            Image("soft")
                                                .resizable()
                                                .frame(height: 255)
                                        }
                                    }.padding(8).background(Color.white).cornerRadius(4).shadow(radius: 1)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Upvotes: 0

qzhann
qzhann

Reputation: 109

LazyVStack provides an initializer with a pinnedView parameter that does exactly this.

Upvotes: 10

atish vishwakarma
atish vishwakarma

Reputation: 201

You can use List style .listStyle(PlainListStyle()) on List and use Section on iOS 13 +

for Example

 struct ContentView: View {
  var content = MyData()
    var body: some View {
      List {
        ForEach(content.sections, id: \.title) { section in
          Section(content: {
            ForEach(section.rows, id: \.self) { row in
              Text(row)
            }
          }, header: {
            Text(section.title)
          })
        }
      }
      .listStyle(PlainListStyle())
    }
}

Given:

struct MyData {
  struct Section {
    var title: String
    var rows: [String]
  }

  var sections: [Section] = []
}

Upvotes: 4

Lindemann
Lindemann

Reputation: 3386

Use pinnedViews in the LazyVStack initializer.

LazyVStack(pinnedViews: [.sectionHeaders]) {
    Section(header: Text("Sticky Header")) {
        ForEach(0...3) { item in
            Text(item)
        }
    }
}

Upvotes: 12

Enea Dume
Enea Dume

Reputation: 3232

SwiftUI’s list view has built-in support for sections and section headers, just like UITableView in UIKit. To add a section around some cells, start by placing a Section around it.

What we want to do is create a list view that has two sections: one for important tasks and one for less important tasks. Here’s how that looks:

struct ContentView: View {
    var body: some View {
        List {
            Section(header: Text("Important tasks")) {
                TaskRow()
                TaskRow()
                TaskRow()
            }

            Section(header: Text("Other tasks")) {
                TaskRow()
                TaskRow()
                TaskRow()
            }
        }
    }
}

Upvotes: 7

Related Questions