skip to Main Content

Context: I need to pin a view in a ScrollView to the top of the screen when scrolling, so I use a LazyVStack with pinnedViews, set the view I need as Section. All good.

Issue: The ScrollView other views might change the content while the view is scrolled to the bottom, when that happens the screen removes all views and doesn’t display them back unless I scroll to the top.

Question: Is there another way to pin a view to the top? (I tried to use List, but not exactly what I need) Or is possible to make a custom Stack with pinned views?

2

Answers


  1. From personal experience, I have done this using a VStack.

    VStack{ 
        PinnedItems()
        LazyVStack {
            OtherItems()
        } 
    }
    

    Then Pinned items will not scroll and are permanently attached to the top. And the lazyVStack will still be able to scroll underneath.

    Login or Signup to reply.
  2. This is my answer for another post, but it seems like you both are having a similar problem. Download and import TrackableScrollView, and try out the below code. While scrolling, there is a pinned View() which is displayed at the top of the screen.

    Link package: https://github.com/maxnatchanon/trackable-scroll-view

    Code:

    import SwiftUI
    import SwiftUITrackableScrollView //Added
    import Combine
    
    struct GameTabView: View {
    
    @State private var scrollViewContentOffset = CGFloat(0) //Added
    @State var selectedTab: Int = 0
    
    init() {
    UITableView.appearance().sectionHeaderTopPadding = 0
    }
    
    var body: some View {
    listView
        .ignoresSafeArea()
    }
    
    var listView: some View {
    ZStack { //Added
        TrackableScrollView(.vertical, showIndicators: true, contentOffset: $scrollViewContentOffset)  {
            VStack {
                Color.gray.frame(height: 400)
                sectionView
            }
        }
        if(scrollViewContentOffset > 400) {
            VStack {
                headerView
                Spacer()
            }
        }
    }
    }
    
    var sectionView: some View {
    Section {
        tabContentView
            .transition(.scale) // FIXED
            .background(Color.blue)
    } header: {
        headerView
    }
    }
    
    private var headerView: some View {
    ScrollViewReader { proxy in
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 16) {
                Button {
                    withAnimation {
                        selectedTab = 0
                    }
                } label: {
                    Text("AAAA")
                        .padding()
                }
                Button {
                    withAnimation {
                        selectedTab = 1
                    }
                } label: {
                    Text("BBBB")
                        .padding()
                }
                Button {
                    withAnimation {
                        selectedTab = 2
                    }
                } label: {
                    Text("BBBB")
                        .padding()
                }
            }
        }
    }
    .background(Color.green)
    }
    
    @ViewBuilder private var tabContentView: some View {
    switch selectedTab {
    case 0:
        DummyScreen(title: "FIRST", color: .red)
    case 1:
        DummyScreen(title: "SECOND", color: .green)
    case 2:
        DummyScreen(title: "THIRD", color: .blue)
    default:
        EmptyView()
    }
    }
    }
    
    struct DummyScreen: View {
    let title: String
    let color: Color
    var body: some View {
    VStack {
        ForEach(0..<15, id: .self) { index in
            HStack {
                Text("#(index): title (title)")
                    .foregroundColor(Color.black)
                    .font(.system(size: 30))
                    .padding(.vertical, 20)
                Spacer()
            }
            .background(Color.yellow)
        }
    }
    .background(color)
    }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search