SwiftKickMobile / SwiftUIMaterialTabs

Material 3-style tabs and Sticky Headers rolled into one SwiftUI library
MIT License
61 stars 8 forks source link

When the content is scrolled a bit, header size change leads to a buggy resizing #15

Closed chichkanov closed 2 months ago

chichkanov commented 2 months ago
  1. Scroll the content a little bit
  2. Trigger header height change
  3. You can see some random padding added to content. If you start scrolling again the content will jump

Environment: iOS18, iPhone 16 pro max simulator. Latest main branch, commit bb97ec4

https://github.com/user-attachments/assets/e27f2101-0430-40f4-8f95-1e9340b6727f

Code

import SwiftUI
import SwiftUIMaterialTabs

enum Tab: String, Hashable, CaseIterable {
    case first
    case second
}

struct ContentView: View {

    @State var selectedTab: Tab = .first

    @State var showMoreHeaderContent = false

    var body: some View {
        MaterialTabs(
            selectedTab: $selectedTab,
            headerTitle: { context in
                VStack {
                    Text("Material Tabs")
                        .font(.title)

                    if showMoreHeaderContent {
                        Color.red.frame(height: 130)
                    }

                    Text("Some long long description bla\nsecond line of text bla bla bal")
                        .font(.callout)
                        .foregroundStyle(.secondary)
                }
                .animation(.bouncy, value: context.height)
                .frame(maxWidth: .infinity)
                .geometryGroup()
                .padding()
                .headerStyle(OffsetHeaderStyle(fade: true), context: context)
            },
            headerTabBar: { context in
                MaterialTabBar(selectedTab: $selectedTab, sizing: .equalWidth, context: context)
            },
            headerBackground: { context in
                Color.white
            },
            content: {
                firstTabContent()
                secondTabContent()
            }
        )
        .animation(.default, value: showMoreHeaderContent)
    }

    @ViewBuilder private func firstTabContent() -> some View {
        MaterialTabsScroll(tab: Tab.first) { _ in
            LazyVStack {
                Button("Show more content in header") {
                    showMoreHeaderContent.toggle()
                }
                .padding()

                ForEach(0..<100) { index in
                    Text("Row \(index)")
                        .padding()
                }
            }
            .background(Color.yellow.opacity(0.2))
        }
        .materialTabItem(tab: Tab.first, label: .secondary("First"))
    }

    @ViewBuilder private func secondTabContent() -> some View {
        MaterialTabsScroll(tab: Tab.second) { _ in
            LazyVStack {
                ForEach(0..<100) { index in
                    Text("Row \(index)")
                        .padding()
                }
            }
        }
        .materialTabItem(tab: Tab.second, label: .secondary("Second"))
    }
}
wtmoose commented 2 months ago

This is essentially a duplicate of #14

chichkanov commented 2 months ago

This is essentially a duplicate of #14

Sounds good. I'll close it in favor of that one