当前位置:网站首页>Support swiftui! Swift image & Video Browser jfherobrowser is online
Support swiftui! Swift image & Video Browser jfherobrowser is online
2022-07-23 06:42:00 【Jerry Yifeng】
Preface

iOS Under a similar image browser, whether it is OC Version or Swift Many versions have been open source . But as a sixorseven year old iOS developer , And I have accumulated a lot of Social App Experience , I can't help but re create one based on my own ideas and similar components in the current project . without doubt , Open source JFHeroBrowser, The preferred language is Swift( Completely Swift Does not contain any OC Code ), More biased Swifty The way - Protocol oriented processing data model , also Swift Advanced enumeration usage , Namespace, etc , If you want to study in depth Swift, I believe this component will give you a different experience , In addition, the landlord is also developing Flutter, The coding method is also more " Response type ". And built in with most third-party libraries ImageCache( Mostly SDWebImage) Different , This component , Does not include built-in ImageCache, But if you integrate this project as a picture browsing , Network diagram , You need to implement HeroNetworkImageProvider agreement , have access to Kingfisher or SDWebImage Or is it a self-designed image cache in your project , Perfectly solve the problem of component coupling , Refer to the following usage for specific use . In addition, this component supports multiple resource formats , Such as this map (UIImage), Network diagram (url),data( Binary system ), video (url), Even you realize it yourself ImageVM You can also access the resources you want . Don't talk much , Let's look at the specific usage .
Download the installation address
cocoaPods:
pod 'JFHeroBrowser', '1.3.2'
github:
https://github.com/JerryFans/JFHeroBrowser
Usage
First initialize the configuration
As mentioned above , stay Appdelegate didFinish Self access HeroNetworkImageProvider. Realization 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.shared
return true
}
Kingfisher Reference resources
extension HeroNetworkImageProvider: NetworkImageProvider {
func downloadImage(with imgUrl: String, complete: Complete<UIImage>?) {
KingfisherManager.shared.retrieveImage(with: URL(string: imgUrl)!, options: nil) { receiveSize, totalSize in
guard totalSize > 0 else { return }
let progress:CGFloat = CGFloat(CGFloat(receiveSize) / CGFloat(totalSize))
complete?(.progress(progress))
} downloadTaskUpdated: { task in
} completionHandler: { result in
switch result {
case .success(let loadingImageResult):
complete?(.success(loadingImageResult.image))
break
case .failure(let error):
complete?(.failed(error))
break
}
}
}
}
class HeroNetworkImageProvider: NSObject {
@objc static let shared = HeroNetworkImageProvider()
}
SDWebImage Reference resources
extension SDWebImageNetworkImageProvider: NetworkImageProvider {
func downloadImage(with imgUrl: String, complete: Complete<UIImage>?) {
SDWebImageManager.shared.loadImage(with: URL(string: imgUrl)) { receiveSize, totalSize, url in
guard totalSize > 0 else { return }
let progress:CGFloat = CGFloat(CGFloat(receiveSize) / CGFloat(totalSize))
complete?(.progress(progress))
} completed: { image, data, error, _, isfinished, url in
if 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()
}
Then define what you need to browse ViewModule
At present, we support HeroBrowserNetworkImageViewModule、HeroBrowserDataImageViewModule、HeroBrowserLocalImageViewModule、HeroBrowserVideoViewModule Four types ViewModule. Theoretically, it can also be defined AssetImageViewModule( Support browsing pictures from photo albums ), I used it in another unopened album component , therefore ViewModule It is very convenient for users to expand various scenarios , And a single scene , Because some specific scenes are less than scenes , I only provide several common scenarios .
several ViewModule Code example
// video
let vm1 = HeroBrowserVideoViewModule(thumbailImgUrl: "http://image.jerryfans.com/bf.jpg", fileUrlPath: path, provider: HeroNetworkImageProvider.shared, autoPlay: false)
list.append(vm1)
// Local map (UIImage)
list.append(HeroBrowserLocalImageViewModule(image: img))
//data chart (file Image Support binary conversion , perhaps flutter Of Uin8List)
list.append(HeroBrowserDataImageViewModule(data: imageSource[i]))
// Network diagram It is also the most commonly used scenario
list.append(HeroBrowserNetworkImageViewModule(thumbailImgUrl: thumbs[i], originImgUrl: origins[i]))
Then there are specific use examples
Browse the pictures
self Is the current controller , Wrote a hero The namespace of ,viewModules It is defined one by one above viewModule Example , Support video or different pictures VM Mix and match is also possible .
In addition, parameters are supported :
- pageControlType ( Default pageControl Or digital 1/5 similar )
- heroView ( That is, the one you want to zoom in and out imageView, If you don't fill in, there will be no scaling effect , It's just one. alpha The gradient )
- heroBrowserDidLongPressHandle ( Long press callback , You can do something to save pictures 、 Share and other actions )
- imageDidChangeHandle ( After switching pictures , On the previous page imageView Also switch , Can only be dissmiss Return to the corresponding position , If it is not set, it is alpha effect )
- enableBlurEffect Whether to turn on the ground glass background , Default on ,false It's a black background .
self.hero.browserPhoto(viewModules: list, initIndex: indexPath.item) {
[
.pageControlType(.pageControl),
.heroView(cell.imageView),
.heroBrowserDidLongPressHandle({ [weak self] heroBrowser,vm in
self?.longPressHandle(vm: vm)
}),
.imageDidChangeHandle({ [weak self] imageIndex in
guard let self = self else { return nil }
guard let cell = self.collectionView.cellForItem(at: IndexPath(item: imageIndex, section: 0)) as? NetworkImageCollectionViewCell else { return nil }
let rect = cell.convert(cell.imageView.frame, to: self.view)
if self.view.frame.contains(rect) {
return cell.imageView
}
return nil
})
]
}
Browse a single video
effect :

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)
Browse mixed resources ( picture + video , Or multiple videos )
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 in
guard let self = self else { return nil }
guard let btn = self.view.viewWithTag(imageIndex) as? UIButton else { return nil }
return btn.imageView
})
]
}
SwiftUI Support for
The initial idea was through official UIViewController convert to SwiftUI Writing , But many problems are found in the implementation , In particular, there is no way to start with the transition effect . If you want pure SwiftUI Code implementation , It seems that only SwiftUI Rewrite the layout , I hope I can have a try when I am free . But actually ,HeroBrowser It's through modal The way to enter , We have direct access to rootViewController Jump directly , But there is a lack of zoom animation , Using the default alpha Transition , The code is as follows . Ben demo Also submitted to github 了 , If necessary, you can check .
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-qMG2KusP-1658281692470)(http://image.jerryfans.com/swiftui_example.gif)]
Configure initialization code
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
JFHeroBrowserGlobalConfig.default.networkImageProvider = HeroNetworkImageProvider.shared
return true
}
}
@main
struct SwiftUIExampleApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
// Get the top floor vc
let keyWindow = UIApplication.shared.connectedScenes
.map({ $0 as? UIWindowScene })
.compactMap({ $0 })
.first?.windows.first
let myAppRootVC : UIViewController? = keyWindow?.rootViewController
// From a picture GridView Jump browse
LazyVGrid(columns: columns) {
ForEach(1..<origins.count, id:\.self) { index in
ImageCell(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)
}
}
}
Attachment address
- project GitHub Address : JFHeroBrowser
- Example https://github.com/JerryFans/JFHeroBrowser/tree/master/Example
- SwiftUIExample https://github.com/JerryFans/JFHeroBrowser/tree/master/SwiftUIExample
边栏推荐
- LSA related content in OSPF
- R语言绘制日历热图
- Context Encoders: Feature Learning by Inpainting 论文笔记
- 影响接口查询速度的情况
- [machine learning basics] unsupervised learning (5) -- generation model
- 华泰证券ETF基金开户怎么样安全吗
- Day27作业
- urllib的一个类型和六个方法
- Linear regression and logical regression and their implementation
- 2022华为开发者大赛中国区开幕式重磅启动!
猜你喜欢

影响接口查询速度的情况

内存泄漏和溢出

Selenium error reporting solution

Dao smart contract DAPP system development technology

我用Flutter Deskstop做了一个Mars Xlog日志解析工具

我的代码-极速版

Evolution Atlas of interface documents. People who have used the first interface document tool are exposed to their age

Difference between SFM and MVs

PWN stack overflow basic exercise - 1

【高等数学】函数可微与可导的区别
随机推荐
LSA related content in OSPF
剑指offer专项突击版第7天
Node uses the exec method to start child processes
Properties of node process object
2022华为开发者大赛中国区开幕式重磅启动!
R语言绘制 棒棒糖图
MySq 数据库约束
Linear regression and logical regression and their implementation
Stack overflow basic exercise question - 3 (with a comparison of 32 and 64 bit differences)
接口文档进化图鉴, 用过第一款接口文档工具的人暴露年龄了
Idea debug is stuck during startup. Solution
Li Xiang, director of ZTE cloud infrastructure open source and standards: open source risks and open source governance for enterprises
[foundation 3] - structure and function
How to open win11 task manager? Skills and methods of opening win11 Task Manager
Liu Jingjuan, Deputy Secretary General of the open atom open source foundation: Thoughts on the current situation and trend of open source development in China
IDEA DEBUG启动一直卡着不动解决办法
马尔科夫随机场:定义、性质,最大后验概率问题,能量最小化问题
node进程对象的属性
Attack and defense world - hacknote
C primer plus学习笔记 —— 5、指针