Home > OS >  SwiftUI expandable component Animation issue
SwiftUI expandable component Animation issue

Time:07-25

I created a custom bottom bar with horizontal expandable tabs.

I have two animations: (1) tab expand/collapse animation, (2) tab bar translation animation (when some tab was expanded, it affects move other tabs)

struct AirTabView: View {
    
    @Binding var isActive: Bool
    
    var model: TabModel
    var action: (() -> ())
    
    var body: some View {
        HStack(spacing: 10) {
            Image(model.imageName)
                .foregroundColor(.black)
            if isActive {
                Text(model.title)
                    .font(.subheadline)
                    .fontWeight(.medium)
                    .foregroundColor(.init(uiColor: .label)
                    )
                    .lineLimit(1)
            }
        }
        .padding(10)
        .background(isActive ? Color(.secondarySystemBackground) : .clear)
        .cornerRadius(11)
        .onTapGesture(perform: action)
        .animation(.linear(duration: 2), value: isActive)
    }
    
}

struct AirTabBar: View {
    
    var tabs: [TabModel]
    var actions: [TabActionModel]
    
    @State private var selectedIndex = 0
    
    var body: some View {
        HStack(spacing: 10) {
            ForEach(0..<tabs.count, id: \.self) { index in
                AirTabView(isActive: .constant(selectedIndex == index), model: tabs[index]) {
                    selectedIndex = index
                }
            }
            Spacer()
            ForEach(0..<actions.count, id: \.self) { index in
                AirTabActionView(model: actions[index])
            }
            
        }
        .padding(.horizontal, 20)
        .padding(.vertical, 10)
        .background()
        .cornerRadius(16)
        .shadow(
            color: .init(uiColor: .black
                .withAlphaComponent(0.07)
            ),
            radius: 15,
            x: 2)
        .animation(.linear(duration: 2))
    }
    
}

But sometimes, I have a visual bug when text that appears in an expanded cell overlaps the image at the animation start. I want that text always be and appear right side of the image.

Please explain to me what I did wrong. Sometimes RIGHT behavior happens, but I want to understand and fix WRONG

enter image description here

CodePudding user response:

Expected effect is not clear, but observed behavior is due to transition (by default it is opacity), ie. when text is added conditionally it appears with opacity transition.

Here is a demo how it could be managed (so you can tune more if some other effect is needed).

Tested with Xcode 13.4 / iOS 15.5 (some missed things replaced)

demo

Main part:

    HStack(spacing: 10) {
        if isActive {
            HStack {
                Image(systemName: model.imageName)  // system name for testing !!
                    .foregroundColor(.black)
                Text(model.title)
                    .font(.subheadline)
                    .fontWeight(.medium)
                    .foregroundColor(.init(uiColor: .label)
                    )
                    .lineLimit(1)
            }
            .transition(.identity)  // content is same !!
        } else {
            Image(systemName: model.imageName)
                .foregroundColor(.black)
                .transition(.identity)    // same is here !!
        }
    }
    .animation(.none, value: isActive) // << don't animate !!
    .padding(10)

so content of label is not animated and replaced Image <> Image Title, which gives title always appears right after image, and only highlighting box is animated.

Test module on GitHub

  • Related