支持SwiftUI!Swift版图片视频浏览器-JFHeroBrowser上线啦
前言
iOS下類似的圖片瀏覽器不管是OC版本還是Swift版本目前已經開源了不少。但是作為一個六七年的老iOS開發者,以及自己曾經積累了的不少社交App經驗,還是忍不住基于自己的想法以及目前項目中類似的組件重新擼了一個。毫無疑問,此次開源的JFHeroBrowser,首選語言是Swift(完全Swift不包含任何OC代碼),偏向更Swifty的方式-面向協議處理數據模型,還有Swift進階枚舉用法,命名空間等,如果你想深入學習Swift,我相信本組件會讓你有不同的體驗,另外由于樓主同時也在開發Flutter,編碼方式上也是更"響應式"。而且與大多數三方庫內置ImageCache(大多是SDWebImage)不同,本組件,不包含內置的ImageCache,但是如果您集成了本項目作為圖片瀏覽,網絡圖這塊,您需要自行實現HeroNetworkImageProvider協議,可以使用Kingfisher或SDWebImage抑或是你項目中自行設計的圖片緩存,完美解決組件耦合問題,具體使用參考下面用法。另外本組件支持多種資源格式,如本地圖(UIImage),網絡圖(url),data(二進制),視頻(url),甚至你自行實現ImageVM也可以接入你想要的資源。話不多說,我們來看具體使用方式。
下載安裝地址
cocoaPods:
pod 'JFHeroBrowser', '1.3.2'github:
https://github.com/JerryFans/JFHeroBrowser
Usage
首先初始化配置
如上面所說,在Appdelegate didFinish處自行接入HeroNetworkImageProvider。實現func downloadImage(with imgUrl: String, complete: Complete?)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {JFHeroBrowserGlobalConfig.default.networkImageProvider = HeroNetworkImageProvider.shared// JFHeroBrowserGlobalConfig.default.networkImageProvider = SDWebImageNetworkImageProvider.sharedreturn true}Kingfisher參考
extension HeroNetworkImageProvider: NetworkImageProvider {func downloadImage(with imgUrl: String, complete: Complete<UIImage>?) {KingfisherManager.shared.retrieveImage(with: URL(string: imgUrl)!, options: nil) { receiveSize, totalSize inguard totalSize > 0 else { return }let progress:CGFloat = CGFloat(CGFloat(receiveSize) / CGFloat(totalSize))complete?(.progress(progress))} downloadTaskUpdated: { task in} completionHandler: { result inswitch result {case .success(let loadingImageResult):complete?(.success(loadingImageResult.image))breakcase .failure(let error):complete?(.failed(error))break}}} }class HeroNetworkImageProvider: NSObject {@objc static let shared = HeroNetworkImageProvider() }SDWebImage參考
extension SDWebImageNetworkImageProvider: NetworkImageProvider {func downloadImage(with imgUrl: String, complete: Complete<UIImage>?) {SDWebImageManager.shared.loadImage(with: URL(string: imgUrl)) { receiveSize, totalSize, url inguard totalSize > 0 else { return }let progress:CGFloat = CGFloat(CGFloat(receiveSize) / CGFloat(totalSize))complete?(.progress(progress))} completed: { image, data, error, _, isfinished, url inif let error = error {complete?(.failed(error))} else if let image = image {complete?(.success(image))} else {complete?(.failed(nil))}}} }class SDWebImageNetworkImageProvider: NSObject {@objc static let shared = SDWebImageNetworkImageProvider() }然后定義你需要瀏覽的ViewModule
目前支持HeroBrowserNetworkImageViewModule、HeroBrowserDataImageViewModule、HeroBrowserLocalImageViewModule、HeroBrowserVideoViewModule四種類型ViewModule。理論上還可以定義AssetImageViewModule(支持從相冊瀏覽圖片),在我另外一個未開源的相冊組件里面使用了,所以ViewModule的擴展非常方便使用者去擴展各種各樣的場景,而且單一場景,由于某些特定場景比較不場景,我這只提供幾種常用的場景。
幾種ViewModule代碼示例
//視頻 let vm1 = HeroBrowserVideoViewModule(thumbailImgUrl: "http://image.jerryfans.com/bf.jpg", fileUrlPath: path, provider: HeroNetworkImageProvider.shared, autoPlay: false)list.append(vm1)//本地圖(UIImage)list.append(HeroBrowserLocalImageViewModule(image: img))//data圖 (file Image支持轉二進制,或者flutter的Uin8List)list.append(HeroBrowserDataImageViewModule(data: imageSource[i]))//網絡圖 也是最常用場景list.append(HeroBrowserNetworkImageViewModule(thumbailImgUrl: thumbs[i], originImgUrl: origins[i]))然后是具體使用示例
瀏覽圖片
self是當前控制器,寫了一個hero的命名空間,viewModules就是上面一個個定義的viewModule示例,支持視頻或者不同圖片VM混搭也是可以的。
另外支持參數:
- pageControlType (默認pageControl或者數字1/5類似)
- heroView (也就是你要放大縮放那個imageView,如果不填就不會有縮放的效果,就是一個alpha漸變)
- heroBrowserDidLongPressHandle (長按回調,可以做些保存圖片、分享等動作)
- imageDidChangeHandle (切換圖片后,上個頁面的imageView也要切換,才可以dissmiss回到相應位置,如果不設置就是alpha效果)
- enableBlurEffect 是否開啟毛玻璃背景,默認開啟,false就是黑色背景。
瀏覽單個視頻
效果:
let vm = HeroBrowserVideoViewModule(thumbailImgUrl: "http://image.jerryfans.com/w_720_h_1280_d_41_89fd26217dc299a442363581deb75b90_iOS_0.jpg", videoUrl: "http://image.jerryfans.com/w_720_h_1280_d_41_2508b8aa06a2e30d2857f9bcbdfd1de0_iOS.mp4", provider: HeroNetworkImageProvider.shared, autoPlay: true)self.hero.browserVideo(viewModule: vm)瀏覽混合資源(圖片+視頻,或多個視頻)
lazy var list: [HeroBrowserViewModuleBaseProtocol] = {var list: [HeroBrowserViewModuleBaseProtocol] = []let vm = HeroBrowserVideoViewModule(thumbailImgUrl: "http://image.jerryfans.com/w_720_h_1280_d_41_89fd26217dc299a442363581deb75b90_iOS_0.jpg", videoUrl: "http://image.jerryfans.com/w_720_h_1280_d_41_2508b8aa06a2e30d2857f9bcbdfd1de0_iOS.mp4", provider: HeroNetworkImageProvider.shared, autoPlay: true)list.append(vm)list.append(HeroBrowserLocalImageViewModule(image: UIImage(named: "template-1")!))if let path = Bundle.main.path(forResource: "bf.MOV", ofType: nil) {let vm1 = HeroBrowserVideoViewModule(thumbailImgUrl: "http://image.jerryfans.com/bf.jpg", fileUrlPath: path, provider: HeroNetworkImageProvider.shared, autoPlay: false)list.append(vm1)}return list}()self.hero.browserMultiSoures(viewModules: self.list, initIndex: 1) {[.enableBlurEffect(false),.heroView(button.imageView),.imageDidChangeHandle({ [weak self] imageIndex inguard let self = self else { return nil }guard let btn = self.view.viewWithTag(imageIndex) as? UIButton else { return nil }return btn.imageView})]}SwiftUI的支持
一開始的想法是通過官方的UIViewController轉換成SwiftUI的寫法,但實現中發現不少問題,特別是轉場效果無從下手。如果要純SwiftUI代碼實現,看來只能使用SwiftUI布局的方式重寫,期待之后有空可以做個嘗試。但是實際上,HeroBrowser是通過modal的方式進場的,我們直接獲取rootViewController直接跳轉亦可,但是就是缺少縮放動畫,使用了默認的alpha轉場,代碼如下。本demo也提交到github了,有需要可以查閱。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qMG2KusP-1658281692470)(http://image.jerryfans.com/swiftui_example.gif)]
配置初始化代碼
class AppDelegate: NSObject, UIApplicationDelegate {func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {JFHeroBrowserGlobalConfig.default.networkImageProvider = HeroNetworkImageProvider.sharedreturn true} }@main struct SwiftUIExampleApp: App {@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegatevar body: some Scene {WindowGroup {ContentView()}} } //獲取頂層vclet keyWindow = UIApplication.shared.connectedScenes.map({ $0 as? UIWindowScene }).compactMap({ $0 }).first?.windows.firstlet myAppRootVC : UIViewController? = keyWindow?.rootViewController//從一個圖片 GridView 跳轉瀏覽LazyVGrid(columns: columns) {ForEach(1..<origins.count, id:\.self) { index inImageCell(index: index).frame(height: columns.count == 1 ? 300 : 150).onTapGesture {var list: [HeroBrowserViewModule] = []for i in 0..<origins.count {list.append(HeroBrowserNetworkImageViewModule(thumbailImgUrl: thumbs[i], originImgUrl: origins[i]))}myAppRootVC?.hero.browserPhoto(viewModules: list, initIndex: index)}}}附件地址
- 項目GitHub地址: JFHeroBrowser
- Example https://github.com/JerryFans/JFHeroBrowser/tree/master/Example
- SwiftUIExample https://github.com/JerryFans/JFHeroBrowser/tree/master/SwiftUIExample
總結
以上是生活随笔為你收集整理的支持SwiftUI!Swift版图片视频浏览器-JFHeroBrowser上线啦的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串加密解密处理
- 下一篇: Windows 10简单搭建一个局域网W