迭代数组时如何使用转换?

问题描述 投票:0回答:1

我希望在迭代数组的索引时进行转换。我想显示多个通知,7.5 秒后我想通过过渡显示新通知。我尝试了 withAnimation、.transition,但什么也没发生。我该如何解决它或者我做错了什么?

struct SoleInAppNotifications3: View {
    @State private var currentIndex: Int = 0
    @State private var isPaused: Bool = false
    @State var hasImage: Bool? = true
    @State var isActive: Bool = false
    @State var isPressed: Bool = false
    @State var isDismissed: Bool = false
    private var notifications: [NotificationItem] = [NotificationItem(title: "Notification 1", subtitle: "Notification 1 subtitle"), NotificationItem(title: "Notification 2", subtitle: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, se"), NotificationItem(title: "Notification 3", subtitle: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, se") ]

    let timer = Timer.publish(every: 1.5, on: .main, in: .common).autoconnect()

    var body: some View {
            HStack(spacing: .zero) {
                if hasImage ?? false {
                    Image("raiff")
                        .padding(.trailing, 17)
                }
                VStack(alignment: .leading, spacing: .zero) {
                    Text(notifications[currentIndex].title)
                        .foregroundColor(.white)
                        .lineLimit(1)
                        .padding(.bottom, 1)
                    Text(notifications[currentIndex].subtitle)
                        .foregroundColor(.white)
                        .lineLimit(2)
                }

                Spacer()
                VStack(spacing: .zero) {
                    ForEach(0..<notifications.count, id: \.self) { index in
                        bubbleView(isActive: index == currentIndex)
                    }
                }
            }
        .frame(maxWidth: .infinity)
        .padding(17)
        .background(isPressed ? Color.red : Color.black)
        .onReceive(timer) { timer in
            if !isPaused, currentIndex < notifications.count - 1 {
                withAnimation {
                    currentIndex = (currentIndex + 1)
                }
            } else {
                currentIndex = 0
            }
        }
        .transition(.scale)
    }

    private func bubbleView(isActive: Bool) -> some View {
        ZStack {
            if isActive {
                RoundedRectangle(cornerRadius: 3)
                    .fill(Color.gray)
                    .frame(width: 6, height: 24)
                    .overlay(
                        RoundedRectangle(cornerRadius: 3).trim(from:0, to: progress())
                            .foregroundColor(Color.white)
                            .animation(.easeInOut, value: currentIndex)
                    )
            } else {
                Circle()
                    .fill(Color.gray)
                    .frame(width: 6, height: 6)
                    .padding(4)
                    .animation(.easeInOut, value: currentIndex)
            }
        }
    }

    func progress() -> Double {
        return (CGFloat(currentIndex) / (CGFloat(notifications.count) - 1))
    }
}


swift swiftui
1个回答
0
投票

不会发生任何转换,因为即使视图的内容正在更改,相同的视图始终可见。

  • 尝试将
    currentIndex
    设置为带有通知文本的
    id
    上的
    VStack
    ,以便当通知更改时它也会更改。
  • transition
    添加
    VStack
    修饰符。
  • 此外,要查看
    currentIndex
    重置为 0 时的转换,请执行重置
    withAnimation
    :
VStack(alignment: .leading, spacing: .zero) {
    Text(notifications[currentIndex].title)
        .foregroundColor(.white)
        .lineLimit(1)
        .padding(.bottom, 1)
    Text(notifications[currentIndex].subtitle)
        .foregroundColor(.white)
        .lineLimit(2)
}
.id(currentIndex)
.transition(.push(from: .trailing))
.onReceive(timer) { timer in
    if !isPaused, currentIndex < notifications.count - 1 {
        withAnimation {
            currentIndex = (currentIndex + 1)
        }
    } else {
        withAnimation { // <- ADDED
            currentIndex = 0
        }
    }
}

Animation

顺便说一句,

PhaseAnimator
可能是实现此类动画的另一种方式。

© www.soinside.com 2019 - 2024. All rights reserved.