SwiftUIのサポート!画像およびビデオブラウザのSwiftバージョン-JFHeroBrowserはオンラインです

序文

ナゲッツテクノロジーコミュニティのクリエイター署名プログラムの募集に参加しています。リンクをクリックして登録し、送信してください。

OCバージョンであろうとSwiftバージョンであろうと、iOSでの同様の画像ブラウザは多くのオープンソースになっています。しかし、6〜7年の古いiOS開発者として、そして私が蓄積したソーシャルアプリの経験として、私は現在のプロジェクトで自分のアイデアや同様のコンポーネントに基づいて新しいものを再作成せざるを得ませんでした。このオープンソースJFHeroBrowserの優先言語がSwift(完全にSwiftにはOCコードが含まれていない)であることは間違いありません。また、Swiftの高度な列挙の使用法、名前空間だけでなく、より迅速な方法でプロトコル指向のデータモデル処理を優先します。 、など、Swiftを深く学びたい場合は、このコンポーネントによって別の体験が得られると思います。また、地主もFlutterを開発しているため、コーディング方法もより「応答性」が高くなります。また、ほとんどのサードパーティライブラリの組み込みImageCache(主にSDWebImage)とは異なり、このコンポーネントには組み込みImageCacheが含まれていませんが、このプロジェクトを画像ブラウジング、ネットワークマップとして統合する場合は、HeroNetworkImageProviderプロトコルを自分で実装する必要があります。プロジェクトでKingfisher、SDWebImage、または自己設計の画像キャッシュを使用できます。これにより、コンポーネントの結合の問題が完全に解決されます。具体的な使用法については、次の使用法を参照してください。さらに、このコンポーネントは、ローカルマップ(UIImage)、ネットワークマップ(url)、データ(バイナリ)、ビデオ(url)などのさまざまなリソース形式をサポートしており、ImageVMを自分で実装した場合でも、リソースにアクセスできます。欲しいです。余計な手間をかけずに、使い方を見てみましょう。

アドレスをダウンロードしてインストールします

cocoaPods:


pod 'JFHeroBrowser', '1.3.2'

github:

github.com/JerryFans/J…

使用法

最初に構成を初期化します

如上面所说,在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.shared

return true

}

Kingfisher参考


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参考


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()

}

然后定义你需要浏览的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就是黑色背景。


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

})

]

}

浏览单个视频

效果:


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 in

guard 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はモーダルを介してフィールドに入ります。rootViewControllerを直接取得して直接ジャンプできますが、ズームアニメーションがなく、デフォルトのアルファ遷移を使用します。コードは次のとおりです。このデモはgithubにも送信されており、必要に応じて確認できます。

初期化コードを構成する


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()

}

}

}


//获取顶层vc

let keyWindow = UIApplication.shared.connectedScenes

.map({ $0 as? UIWindowScene })

.compactMap({ $0 })

.first?.windows.first

let myAppRootVC : UIViewController? = keyWindow?.rootViewController

//从一个图片 GridView 跳转浏览

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)

}

}

}

添付アドレス

終わり

ナゲッツテクノロジーコミュニティのクリエイター署名プログラムの募集に参加しています。リンクをクリックして登録し、送信してください。

おすすめ

転載: juejin.im/post/7121926583786405902