当前位置:网站首页>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

原网站

版权声明
本文为[Jerry Yifeng]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/204/202207221846486298.html