Activity indicator in SwiftUI

后端 未结 9 2045
忘了有多久
忘了有多久 2020-11-29 17:36

Trying to add a full screen activity indicator in SwiftUI.

I can use .overlay(overlay: ) function in View Protocol.

With this, I c

9条回答
  •  伪装坚强ぢ
    2020-11-29 18:19

    Custom Indicators

    Although Apple supports native Activity Indicator now from the SwiftUI 2.0, You can Simply implement your own animations. These are all supported on SwiftUI 1.0. Also it is working in widgets.

    Arcs

    struct Arcs: View {
        @Binding var isAnimating: Bool
        let count: UInt
        let width: CGFloat
        let spacing: CGFloat
    
        var body: some View {
            GeometryReader { geometry in
                ForEach(0.. some View {
            Group { () -> Path in
                var p = Path()
                p.addArc(center: CGPoint(x: geometrySize.width/2, y: geometrySize.height/2),
                         radius: geometrySize.width/2 - width/2 - CGFloat(index) * (width + spacing),
                         startAngle: .degrees(0),
                         endAngle: .degrees(Double(Int.random(in: 120...300))),
                         clockwise: true)
                return p.strokedPath(.init(lineWidth: width))
            }
            .frame(width: geometrySize.width, height: geometrySize.height)
        }
    }
    

    Demo of different variations


    Bars

    struct Bars: View {
        @Binding var isAnimating: Bool
        let count: UInt
        let spacing: CGFloat
        let cornerRadius: CGFloat
        let scaleRange: ClosedRange
        let opacityRange: ClosedRange
    
        var body: some View {
            GeometryReader { geometry in
                ForEach(0.. CGFloat {
            (geometry.width/CGFloat(count)) - (spacing-2)
        }
    
        private func item(forIndex index: Int, in geometrySize: CGSize) -> some View {
            RoundedRectangle(cornerRadius: cornerRadius,  style: .continuous)
                .frame(width: size(count: count, geometry: geometrySize), height: geometrySize.height)
                .scaleEffect(x: 1, y: scale, anchor: .center)
                .opacity(opacity)
                .animation(
                    Animation
                        .default
                        .repeatCount(isAnimating ? .max : 1, autoreverses: true)
                        .delay(Double(index) / Double(count) / 2)
                )
                .offset(x: CGFloat(index) * (size(count: count, geometry: geometrySize) + spacing))
        }
    }
    

    Demo of different variations


    Blinkers

    struct Blinking: View {
        @Binding var isAnimating: Bool
        let count: UInt
        let size: CGFloat
    
        var body: some View {
            GeometryReader { geometry in
                ForEach(0.. some View {
            let angle = 2 * CGFloat.pi / CGFloat(count) * CGFloat(index)
            let x = (geometrySize.width/2 - size/2) * cos(angle)
            let y = (geometrySize.height/2 - size/2) * sin(angle)
            return Circle()
                .frame(width: size, height: size)
                .scaleEffect(isAnimating ? 0.5 : 1)
                .opacity(isAnimating ? 0.25 : 1)
                .animation(
                    Animation
                        .default
                        .repeatCount(isAnimating ? .max : 1, autoreverses: true)
                        .delay(Double(index) / Double(count) / 2)
                )
                .offset(x: x, y: y)
        }
    }
    

    Demo of different variations


    For the sake of preventing walls of code, you can find more elegant indicators in this repo hosted on the git.

    Note that all these animations have a Binding that MUST toggle to be run.

提交回复
热议问题