第十六章 RoundedRectangle|aspectRatio|UIViewRepresentable

RoundedRectangle 自定义 HUD

在我们进行登陆请求的时候,界面上毫无反馈,我们想加上 Loading 动画,等接口完毕就提示登录成功或者登录失败。

虽然有很多优秀的第三方 HUD,但是我觉得这么简单的也不需要用第三方了,我们尝试自己写一下试一下。

我们在 View 文件夹,新建一个 HUDView.swift文件。

swift 复制代码
struct HUDView: View {
    var body: some View {
        Text("Hello World!")
    }
}

我们想做一个效果就是,大概是下面的效果。

那么我们就需要用到 ZStack 垂直布局,最下面 我们需要用到 一个黑色圆角的试图,那么就需要 RoundedRectangle 。

swift 复制代码
var body: some View {
    ZStack {
        RoundedRectangle(cornerRadius: 20)
    }
}

aspectRatio 填充模式

因为 RoundedRectangle 没有任何内容可计算自己的大小,所以会按照最大的宽度和最大的高度进行充满。

我们需要一个正方形,那么就需要宽度和长度进行一比一的大小。

swift 复制代码
.aspectRatio(contentMode: .fit)

目前宽度和高度都是一样的大小,但是宽度铺满不符合,那么我们设置一下 宽度。

swift 复制代码
.frame(width:150)

UIViewRepresentable 封装 UIView 为 View

我们希望控件的中间放一个系统的 ActivityIndicatorView,来表示当前正在请求。但是在 SwiftUI 里面,系统并没有提供这样的控件可以用。

那么我们需要将 UIKit中的 UIActivityIndicatorView 转换给 SwiftUI 用。

我们将在 View的文件夹新建一个 ActivityIndicatorView.swift文件。

swift 复制代码
struct ActivityIndicatorView: UIViewRepresentable {
    typealias UIViewType = UIActivityIndicatorView
    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let activityIndicatorView = UIActivityIndicatorView()
        return activityIndicatorView
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
        
    }
}

我们遇到了一个 全新的 View 的协议 UIViewRepresentable,这个允许我们可以将 UIView 的试图轻松的转换成 SwiftUI 的类型。

主要需要实现 makeUIView 函数和 updateUIView 函数。

因为 ActivityIndicatorView 是结构体,ActivityIndicatorView初始化时候会调用 makeUIView 生成对应的试图,当 @State值变化时候,会调用 updateUIView 更新试图。

关于 UIViewRepresentable 详细的介绍可以查看文章

betterprogramming.pub/how-to-use-...

此时我们 ActivityIndicatorView 试图预览看不出任何内容。

那是因为默认 isAnimating = false,会自动隐藏控件。我们设置一个 @Binding 的组件控制 UIActivityIndicatorView 的开始动画和结束动画。

swift 复制代码
struct ActivityIndicatorView: UIViewRepresentable {
    
    @Binding var isAnimating:Bool
    
    typealias UIViewType = UIActivityIndicatorView
    func makeUIView(context: Context) -> UIActivityIndicatorView {
        let activityIndicatorView = UIActivityIndicatorView()
        return activityIndicatorView
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {
        if isAnimating {
            uiView.startAnimating()
        } else {
            uiView.stopAnimating()
        }
    }
}

我们设置外面传进来 @Binding的值为true,此时我们可以预览看到小小的菊花。但是觉得 UIActivityIndicatorView 的组件有点小,我们设置为样式为 large

swift 复制代码
activityIndicatorView.style = .large

这个灰色自然不能满足我们控件的需求,你想我们在黑色背景下面显示灰色,估计眼睛都可以看瞎了。我们新建一个变量,可以设置UIActivityIndicatorView 的颜色。

swift 复制代码
/// ActivityIndicatorView
let color:UIColor?
@Binding var isAnimating:Bool

init(isAnimating:Binding<Bool>,
     color:UIColor? = nil) {
    _isAnimating = isAnimating
    self.color = color
}

/// makeUIView
if let color = color {
    activityIndicatorView.color = color
}

现在我们就可以将 ActivityIndicatorView 组件用在我们的 HUDView上面了。

这么看起来,效果还不错。但是背景颜色太黑了,我们设置一下透明度,让可以隐约的看到下面的试图,并且看上去没有那么黑。


但是我们感觉我们的 HUDView 试图还是太大了,我们觉得如果按照里面的内容设置 Padding 岂不是最好了。

我们将 RoundedRectangle 设置为 ActivityIndicatorView Background 试图,并且设置 Padding = 20

为了外界可以控制 HUDView 的开始动画和结束动画,我们将修改代码如下。

控件我们完成了,我们新建一个 HUDViewModify 来让其他界面方便的进行调用。

我们再新增一个 View 的扩展。

到目前为止,我们简单版本的 HUD 就封装完毕了。对于大家日常开发过程中,优先可以选择第三方的控件使用,但是要理解他们是怎样实现的。

不能只作为一个只会使用工具的工具人。

相关推荐
君赏3 小时前
第十八章 封装HUD和完善登录界面逻辑
swiftui
君赏3 小时前
第十五章 Task|NSAppTransportSecurity|keyDecodingStrategy
swiftui
君赏3 小时前
第十四章 async/await|overlay|PreferencrKey|Anchor
swiftui
君赏3 小时前
第十三章 Button|cornerRadius
swiftui
君赏3 小时前
第六章 Published|ObservedObject|EnvironmentObject|Environment
swiftui
君赏3 小时前
第八章 封装MVVM|onTapGesture|AppStorage
swiftui
君赏3 小时前
第十二章 TextField|EmptyView|SecureField
swiftui
君赏3 小时前
第四章 Preview Device|Expand|Alignment|LineLimit|Rectangle|ForegroundColor
swiftui
君赏3 小时前
第七章 组件提炼|代码清爽|Padding
swiftui