SwiftUIMaterialTabs icon indicating copy to clipboard operation
SwiftUIMaterialTabs copied to clipboard

content doesn't animate when header size changes. Header animation is janky

Open chichkanov opened this issue 5 months ago • 3 comments

  1. Add some toggle to trigger header height change
  2. Add .animation or change the toggle value using withAnimation {}
  3. Header size change animation is janky. Content (with yellow background) doesn't respect the animation and instantly moves to a new position

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

https://github.com/user-attachments/assets/578e7d92-9ceb-4f3a-b816-2b243444d05f

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"))
    }
}

chichkanov avatar Sep 18 '24 10:09 chichkanov