SwiftUI

SwiftUIのCircleコンポーネントを使ってインジケーターを作成する

SwiftUIでの図形の描写とアニメーションに関するドキュメントを探していたら

こちらに書いていました。

今回はSwiftUIのCircleコンポーネントを使って簡単なインジケーターを作成したと思います。前回はUIViewRepresentableを用いれば既存のUIKitのコンポーネントをSwiftUIでも利用できることを学びました。

今回はそれを応用してSwiftUIでよくiOSのライブラリになっているインジケーターを開発してみます。

ソースコードについて

いきなりですが、完成品のソースコードを載せます。

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        NavigationView{
            Home()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct Home: View {
    /// ローディング中かどうか
    @State var isLoading = false
    
    var body: some View {
        ZStack {
            VStack(spacing: 25) {
                Button(action: {
                    isLoading.toggle()
                }, label: {
                    Text("インジケーター")
                })
            }
            if isLoading {
                HUDProgressView(placeHolder: "ローディング中", isShow: $isLoading)
            }
        }
        .edgesIgnoringSafeArea(.all)
    }
}

struct HUDProgressView: View {
    var placeHolder: String
    @Binding var isShow: Bool
    @State var animated = false
    
    var body: some View {
        VStack(spacing: 28) {
            Circle()
                .stroke(AngularGradient(gradient: .init(colors: [Color.primary, Color.primary.opacity(0)]), center: .center))
                .frame(width: 80, height: 80)
                .rotationEffect(.init(degrees: animated ? 360: 0))
            
            Text(placeHolder)
                .fontWeight(.bold)

        }
        .padding(.vertical, 25)
        .padding(.horizontal, 35)
        .background(BlurView())
        .cornerRadius(20)
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(
            Color.primary.opacity(0.35)
                .onTapGesture {
                    withAnimation {
                        isShow.toggle()
                    }
                }
        )
        .onAppear {
            withAnimation(Animation.linear(duration: 1.5).repeatForever(autoreverses: false)) {
                animated.toggle()
            }
        }
    }
}

struct BlurView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIVisualEffectView {
        let view = UIVisualEffectView(effect: UIBlurEffect(style: .systemThinMaterial))
        return view
    }
    
    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
        
    }
}

こちらをビルドすると次のような画面が表示されます。


前回のUIViewRepresentableプロトコルに準拠させたBlueViewの構造体をを背景色にしてCircleを描写されてます。BlueViewはUIVisualEffectViewをSwiftUIで利用できるようにしたコンポーネントです。

それでは、バイバイ。

ABOUT ME
tamappe
都内で働くiOSアプリエンジニアのTamappeです。 当ブログではモバイルアプリの開発手法について紹介しています。メインはiOS、サブでFlutter, Android も対応できます。 執筆・講演のご相談は tamapppe@gmail.com までお問い合わせください。