SwiftUI 基础之提示框Activity Indicator制作

SwiftUI目前还在发展阶段,有些视图还未能提供。但是苹果给我们提供复用机制,很容易将历史代码移植到SwiftUI世界中。下面我们通过UIViewRepresentable将UIKit的UIActivityIndicator封装一下

最终效果

SwiftUI 基础之提示框Activity Indicator制作_第1张图片
SwiftUI 基础之提示框Activity Indicator制作

实现步骤

首先,我们将UIActivityIndi​​cator包装到一个ActivityIndi​​cator视图中,该视图可用作SwiftUI视图。其中 isAnimating作为动画的开关

struct ActivityIndicator: UIViewRepresentable {
    
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style
    
    func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}

在实际开发中,我们很少单独使用UIActivityIndi​​cator,因为实在太单调了。我通常是添加UILabel来告知用户我们正在处理的事项,例如:加载,计算,载入等,在SwiftUI世界里我们用Text就可以很好的完成这个任务。

由于我们现在将ActivityIndi​​cator作为SwiftUI视图,因此我们可以轻松地利用SwiftUI强大组合功能,联合其他View来创建功能强大的HUD(Head up Display))提示框。

另外,为此了示范loading页面的显示与隐藏,我们还增加了隐藏和显示按钮。


SwiftUI 基础之提示框Activity Indicator制作_第2张图片
显示按钮效果

显示按钮代码

   Button(action:{
                    self.isShowing = !self.isShowing
                    //self.isAnimating = false
                    
                }){
                    Text(" Show loading ").foregroundColor(.white)
                }.background(Color.orange)
                    .cornerRadius(2.0)
                .shadow(radius: 2)

隐藏按钮效果


SwiftUI 基础之提示框Activity Indicator制作_第3张图片
隐藏按钮效果

隐藏按钮代码

  Button(action:{
                        self.isShowing = false
                        //self.isAnimating = false
                        
                    }){
                        Text(" Hide ")
                    }.background(Color.white)
                        .cornerRadius(2.0)
                    .shadow(radius: 2)

组装

struct LoadingView: View where Content: View {
    
    @Binding var isShowing: Bool
    @State var isAnimating: Bool = true
    var content: () -> Content
    
    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .center) {
                
                self.content()
                    .disabled(self.isShowing)
                    .blur(radius: self.isShowing ? 3 : 0)
                
                
                VStack {
                    Text("Loading...")
                    ActivityIndicator(isAnimating: self.$isAnimating, style: .large)
                    Button(action:{
                        self.isShowing = false
                        //self.isAnimating = false
                        
                    }){
                        Text(" Hide ")
                    }.background(Color.white)
                        .cornerRadius(2.0)
                    .shadow(radius: 2)
                }
                    
                .frame(width: geometry.size.width / 2,
                       height: geometry.size.height / 5)
                    .background(Color.secondary.colorInvert())
                    .foregroundColor(Color.primary)
                    .cornerRadius(20)
                    .opacity(self.isShowing ? 1 : 0)
                
            }
        }
    }
    
}


主页面

struct ContentView: View {
    @State var isShowing: Bool = true
    var body: some View {
        
        LoadingView(isShowing:self.$isShowing) {
            VStack{
                Button(action:{
                    self.isShowing = !self.isShowing
                    //self.isAnimating = false
                    
                }){
                    Text(" Show loading ").foregroundColor(.white)
                }.background(Color.orange)
                    .cornerRadius(2.0)
                .shadow(radius: 2)
                
                NavigationView {
                    List(["1", "2", "3", "4", "5"], id: \.self) { row in
                        Text(row)
                    }.navigationBarTitle(Text("A List"), displayMode: .large)
                }
            }
        }
    }
}

项目完整代码

import SwiftUI
struct ActivityIndicator: UIViewRepresentable {
    
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style
    
    func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}
struct LoadingView: View where Content: View {
    
    @Binding var isShowing: Bool
    @State var isAnimating: Bool = true
    var content: () -> Content
    
    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .center) {
                
                self.content()
                    .disabled(self.isShowing)
                    .blur(radius: self.isShowing ? 3 : 0)
                
                
                VStack {
                    Text("Loading...")
                    ActivityIndicator(isAnimating: self.$isAnimating, style: .large)
                    Button(action:{
                        self.isShowing = false
                        //self.isAnimating = false
                        
                    }){
                        Text(" Hide ")
                    }.background(Color.white)
                        .cornerRadius(2.0)
                    .shadow(radius: 2)
                }
                    
                .frame(width: geometry.size.width / 2,
                       height: geometry.size.height / 5)
                    .background(Color.secondary.colorInvert())
                    .foregroundColor(Color.primary)
                    .cornerRadius(20)
                    .opacity(self.isShowing ? 1 : 0)
                
            }
        }
    }
    
}

struct ContentView: View {
    @State var isShowing: Bool = true
    var body: some View {
        
        LoadingView(isShowing:self.$isShowing) {
            VStack{
                Button(action:{
                    self.isShowing = !self.isShowing
                    //self.isAnimating = false
                    
                }){
                    Text(" Show loading ").foregroundColor(.white)
                }.background(Color.orange)
                    .cornerRadius(2.0)
                .shadow(radius: 2)
                
                NavigationView {
                    List(["1", "2", "3", "4", "5"], id: \.self) { row in
                        Text(row)
                    }.navigationBarTitle(Text("A List"), displayMode: .large)
                }
            }
        }
    }
}

参考资料

https://peacemoon.de/blog/2019/06/10/activity-indicator-with-swiftui/

更多SwiftUI教程和代码关注专栏

QQ:3365059189
SwiftUI技术交流QQ群:518696470

  • 请关注我的专栏icloudend, SwiftUI教程与源码
    https://www.jianshu.com/c/7b3e3b671970

你可能感兴趣的:(SwiftUI 基础之提示框Activity Indicator制作)