最近更新了2.0版本焦人,解決了1.0版本的問題挥吵,并進(jìn)行了優(yōu)化。
當(dāng)前版本沒有更新庫花椭,因為網(wǎng)絡(luò)不太好忽匈,所以會直接放源碼。
先說思路矿辽,1.0版本的思路是直接在入口contentView上方一個View丹允,在有彈框需求時就展示這個view郭厌,并在上面展示hud,全局只有一個hud雕蔽,面對同時多個請求都需要展示彈框的需求就無法滿足折柠。針對這點,2.0優(yōu)化為了一組彈框批狐,在彈框管理器中有兩組數(shù)據(jù)扇售,一組管理臨時彈框,一組管理組合彈框嚣艇,每次彈框但是由單獨的對象進(jìn)行管理承冰,不會出現(xiàn)1.0的互相干擾問題。用法沒有任何改變食零。
FDHud的優(yōu)點:跟界面代碼完全撇開困乒,在任何數(shù)據(jù)、邏輯地區(qū)都能任意調(diào)用并進(jìn)行展示贰谣,使用代碼極少娜搂,使用風(fēng)格跟UIKit的彈框保持一致。
缺點:(如果沒得非push界面冈爹,就不存在此問題涌攻。全屏彈框也算不上問題)
最近使用發(fā)現(xiàn)的,在完全swiftUI的界面代碼下频伤,無法單獨為窗口進(jìn)行任何代碼設(shè)置恳谎,而入口的
showFDHud 代碼,僅適用于當(dāng)前View憋肖。表現(xiàn)為在彈出界面上無法直接展示因痛。比如,界面彈出一個登錄界面岸更,登錄界面是無法直接展示FDHud的彈框鸵膏,需要在被彈出界面再次調(diào)用showFDHud,才能展示彈框怎炊。這會導(dǎo)致另一個問題谭企,因為showFDHud是添加一個可放置彈框的背景,所以在登錄和主界面都會同步彈框评肆,畢竟使用的是同一個數(shù)據(jù)源债查,如果是登錄界面是全屏的,則界面上是沒有任何瑕疵的瓜挽。
pod沒更新盹廷,demo更新了 ,去掉了HUD出現(xiàn)時的動畫久橙,因為如果有兩個相近的接連show俄占,會導(dǎo)致崩潰
前言:
最近在學(xué)習(xí)swiftUI管怠,發(fā)現(xiàn)這玩意跟以前的UIKit框架差別還是挺大,許多思維都需要重新發(fā)散就比如彈框缸榄,在UIkit里面渤弛,是想在哪個界面彈框就能直接去彈出來,而且在swiftUI里面碰凶,如果不是直接在響應(yīng)方法暮芭,而是在邏輯處理方法里面想要彈框,就只能一開始就布局欲低,然后用狀態(tài)管理器去控制展現(xiàn)辕宏,就不如UIKit自由和自在,尤其是對于剛學(xué)習(xí)swiftUI的人來說砾莱,容易卡殼瑞筐。在一段時間學(xué)習(xí)后,我嘗試在項目運用學(xué)習(xí)成果腊瑟,在網(wǎng)絡(luò)請求的時候聚假,就發(fā)現(xiàn)了加載請求彈框的問題,度娘了之后闰非,也發(fā)現(xiàn)了別人的成果膘格,但是使用方面感覺完全沒得以前的使用自由,方便财松,所以瘪贱,結(jié)合別人的思路和自己的成果,寫出了這個控件辆毡,以達(dá)到在使用UIkit時的手感菜秦。
一 集成
集成非常簡單,使cocoaPods集成
pod 'FDHudView'
在入口做簡單的設(shè)置,在根視圖上注冊使用
import SwiftUI
import FDHudView
@main
struct DJLContractorApp: App {
var body: some Scene {
WindowGroup {
TabbarView(manager: TabbarManager.manager)
.showFDHud()
}
}
}
使用介紹
然后在任何需要使用的地方進(jìn)行使用
加載簡單的文字菊花效果
FDHud.show("加載中...")
加載純文字提示
FDHud.showMessage("加載中...")
網(wǎng)絡(luò)數(shù)據(jù)加載 **注意,這是匹配使用的舶掖,一個負(fù)責(zé)展示球昨,一個負(fù)責(zé)消除
FDHud.showLoading()
FDHud.hideHud()
目前就三個簡單的樣式,因為代碼也是簡潔明了眨攘,需要的可以自己修改成自己需要的樣式
FDHudView的特點就是全局就這一個主慰,通過一個單例管理對象進(jìn)行控制,如果界面已經(jīng)展示了鲫售,再次調(diào)用show方法河哑,會失效。目前還沒做多次調(diào)用等的優(yōu)化龟虎,只是一個最簡單的使用版本,勿噴沙庐,不接受鲤妥。
地址是demo佳吞,也可以下載后把FDHud文件夾直接拖進(jìn)工程使用
Github 地址傳送門
下面是斯坦福的教學(xué)視頻,2020棉安,2021的底扳,兩期內(nèi)容大致一樣,但是2021的相對更完善更全面贡耽,可以直接只看2021年的衷模,當(dāng)然,時間多的也可以全看蒲赂,話說阱冶,這個老大爺還是很有喜感的,講的也很好
學(xué)習(xí)地址傳送門
2.0源碼
管理器
import UIKit
import SwiftUI
class FSHud: ObservableObject {
static let manager = FSHud()
@Published var hudList = [FSHudItem]()
@Published var hudLoadingList = [FSHudItem]()
@Published var isShow: Bool = false
public static func show(_ text: String) {
manager.show(text)
}
public static func showMessage(_ text: String) {
manager.showMessage(text)
}
public static func showLoading() {
manager.showLoading()
}
public static func hideHud() {
manager.hideHud()
}
private func show(_ text: String) {
isShow = true
let item = FSHudItem()
item.text = text
item.type = .textIcon
withAnimation {
hudList.append(item)
}
item.startDispatchTime {
self.hudList.removeAll(where: { $0.id == item.id })
self.checkIsShow()
}
}
private func showMessage(_ text: String) {
isShow = true
let item = FSHudItem()
item.text = text
item.type = .text
withAnimation {
hudList.append(item)
}
item.startDispatchTime {
self.hudList.removeAll(where: { $0.id == item.id })
self.checkIsShow()
}
}
private func showLoading() {
isShow = true
let item = FSHudItem()
item.type = .icon
withAnimation {
hudLoadingList.append(item)
}
}
private func hideHud() {
if !hudLoadingList.isEmpty {
hudLoadingList.removeLast()
}
checkIsShow()
}
private func checkIsShow() {
if hudList.isEmpty && hudLoadingList.isEmpty {
isShow = false
}
}
}
final class FSHudItem {
var id = Date().timeIntervalSince1970
var text: String?
var type = FDHudType.text
func startDispatchTime(_ block: @escaping () -> ()) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
block()
}
}
}
extension View {
public func showFSHud() -> some View {
self.modifier(FSHudVM())
}
}
struct FSHudVM: ViewModifier {
func body(content: Content) -> some View {
ZStack(alignment: .center) {
content
FSHudView()
.zIndex(1)
}
}
}
界面代碼
struct FSHudView: View {
@ObservedObject var viewModel = FSHud.manager
var body: some View {
if viewModel.isShow {
ZStack {
ForEach(viewModel.hudList, id: \.id) { item in
FSHudItemView(item: item)
}
.padding(.horizontal, 0)
.padding(12)
.background(
RoundedRectangle(cornerRadius: 4).fill(Color.hex(0x000000, 0.7))
.shadow(color: Color(.black).opacity(0.16), radius: 12, x: 0, y: 5)
)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(
Color.clear.ignoresSafeArea()
)
}
}
}
struct FSHudItemView: View {
var item: FSHudItem
var body: some View {
if item.type == .text {
textContent
} else if item.type == .icon {
iconContent
} else {
textIconContent
}
}
}
extension FSHudItemView {
var textContent: some View {
Text(item.text ?? "")
.foregroundColor(.white)
}
var iconContent: some View {
Image(systemName: "rays").imageScale(.large).spinning()
.padding([.top,.leading,.trailing,.bottom],10)
.foregroundColor(Color.white)
}
var textIconContent: some View {
VStack {
Image(systemName: "rays").imageScale(.large).spinning()
.padding([.top,.leading,.trailing,.bottom],10)
.foregroundColor(Color.white)
Text(item.text ?? "")
.foregroundColor(.white)
}
}
}