├── .gitignore
├── ARTICLE.md
├── Assets
├── Browser.png
├── Home.gif
├── Introduction.gif
├── Transition.png
├── gifImage.gif
├── rawImage.jpg
└── testwebp.webp
├── CHANGELOG.md
├── Example
├── Example.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Example.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Example
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── 图片浏览器iPadApp_76pt.png
│ │ │ ├── 图片浏览器iPadApp_76pt@2x.png
│ │ │ ├── 图片浏览器iPadNotifications_20pt.png
│ │ │ ├── 图片浏览器iPadNotifications_20pt@2x.png
│ │ │ ├── 图片浏览器iPadProApp_83.5pt@2x.png
│ │ │ ├── 图片浏览器iPadSpootlight5_29pt.png
│ │ │ ├── 图片浏览器iPadSpootlight5_29pt@2x.png
│ │ │ ├── 图片浏览器iPadSpootlight7_40pt.png
│ │ │ ├── 图片浏览器iPadSpootlight7_40pt@2x.png
│ │ │ ├── 图片浏览器iPhoneApp_60pt@2x.png
│ │ │ ├── 图片浏览器iPhoneApp_60pt@3x.png
│ │ │ ├── 图片浏览器iPhoneNotification_20pt@2x.png
│ │ │ ├── 图片浏览器iPhoneNotification_20pt@3x.png
│ │ │ ├── 图片浏览器iPhoneSpootlight5_29pt@2x.png
│ │ │ ├── 图片浏览器iPhoneSpootlight5_29pt@3x.png
│ │ │ ├── 图片浏览器iPhoneSpootlight7_40pt@2x.png
│ │ │ ├── 图片浏览器iPhoneSpootlight7_40pt@3x.png
│ │ │ └── 图片浏览器store_1024pt.png
│ │ ├── Contents.json
│ │ ├── local_0.imageset
│ │ │ ├── Contents.json
│ │ │ └── local_0.jpeg
│ │ ├── local_1.imageset
│ │ │ ├── Contents.json
│ │ │ └── local_1.png
│ │ ├── local_2.imageset
│ │ │ ├── Contents.json
│ │ │ └── local_2.jpeg
│ │ ├── local_3.imageset
│ │ │ ├── Contents.json
│ │ │ └── local_3.jpeg
│ │ ├── local_4.imageset
│ │ │ ├── Contents.json
│ │ │ └── local_4.jpeg
│ │ └── local_5.imageset
│ │ │ ├── Contents.json
│ │ │ └── local_5.jpeg
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── BaseCollectionViewCell.swift
│ ├── BaseCollectionViewController.swift
│ ├── DataSourceAppendViewController.swift
│ ├── DataSourceDeleteViewController.swift
│ ├── DefaultPageIndicatorViewController.swift
│ ├── GIFViewController.swift
│ ├── HomeViewController.swift
│ ├── ImageSmoothZoomViewController.swift
│ ├── ImageZoomViewController.swift
│ ├── Info.plist
│ ├── JXNamespace.swift
│ ├── JXPhotoBrowserProgressView.swift
│ ├── KingfisherImageViewController.swift
│ ├── LoadingProgressViewController.swift
│ ├── LocalImageViewController.swift
│ ├── MoreDetailViewController.swift
│ ├── MultipleCellViewController.swift
│ ├── MultipleSectionViewController.swift
│ ├── NumberPageIndicatorViewController.swift
│ ├── Photos.plist
│ ├── PushNextViewController.swift
│ ├── RawImageViewController.swift
│ ├── ResourceModel.swift
│ ├── SDWebImageViewController.swift
│ ├── SceneDelegate.swift
│ ├── UICollectionView+JX.swift
│ ├── UITableView+JX.swift
│ ├── VerticalBrowseViewController.swift
│ ├── VideoCell.swift
│ ├── VideoPhotoViewController.swift
│ ├── video_0.MP4
│ ├── video_1.MP4
│ └── video_2.MP4
├── Podfile
├── Podfile.lock
├── Pods
│ ├── Kingfisher
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── Sources
│ │ │ ├── Cache
│ │ │ ├── CacheSerializer.swift
│ │ │ ├── DiskStorage.swift
│ │ │ ├── FormatIndicatedCacheSerializer.swift
│ │ │ ├── ImageCache.swift
│ │ │ ├── MemoryStorage.swift
│ │ │ └── Storage.swift
│ │ │ ├── Extensions
│ │ │ ├── CPListItem+Kingfisher.swift
│ │ │ ├── ImageView+Kingfisher.swift
│ │ │ ├── NSButton+Kingfisher.swift
│ │ │ ├── NSTextAttachment+Kingfisher.swift
│ │ │ ├── TVMonogramView+Kingfisher.swift
│ │ │ ├── UIButton+Kingfisher.swift
│ │ │ └── WKInterfaceImage+Kingfisher.swift
│ │ │ ├── General
│ │ │ ├── ImageSource
│ │ │ │ ├── AVAssetImageDataProvider.swift
│ │ │ │ ├── ImageDataProvider.swift
│ │ │ │ ├── Resource.swift
│ │ │ │ └── Source.swift
│ │ │ ├── KF.swift
│ │ │ ├── KFOptionsSetter.swift
│ │ │ ├── Kingfisher.swift
│ │ │ ├── KingfisherError.swift
│ │ │ ├── KingfisherManager.swift
│ │ │ └── KingfisherOptionsInfo.swift
│ │ │ ├── Image
│ │ │ ├── Filter.swift
│ │ │ ├── GIFAnimatedImage.swift
│ │ │ ├── GraphicsContext.swift
│ │ │ ├── Image.swift
│ │ │ ├── ImageDrawing.swift
│ │ │ ├── ImageFormat.swift
│ │ │ ├── ImageProcessor.swift
│ │ │ ├── ImageProgressive.swift
│ │ │ ├── ImageTransition.swift
│ │ │ └── Placeholder.swift
│ │ │ ├── Networking
│ │ │ ├── AuthenticationChallengeResponsable.swift
│ │ │ ├── ImageDataProcessor.swift
│ │ │ ├── ImageDownloader.swift
│ │ │ ├── ImageDownloaderDelegate.swift
│ │ │ ├── ImageModifier.swift
│ │ │ ├── ImagePrefetcher.swift
│ │ │ ├── RedirectHandler.swift
│ │ │ ├── RequestModifier.swift
│ │ │ ├── RetryStrategy.swift
│ │ │ ├── SessionDataTask.swift
│ │ │ └── SessionDelegate.swift
│ │ │ ├── PrivacyInfo.xcprivacy
│ │ │ ├── SwiftUI
│ │ │ ├── ImageBinder.swift
│ │ │ ├── ImageContext.swift
│ │ │ ├── KFAnimatedImage.swift
│ │ │ ├── KFImage.swift
│ │ │ ├── KFImageOptions.swift
│ │ │ ├── KFImageProtocol.swift
│ │ │ └── KFImageRenderer.swift
│ │ │ ├── Utility
│ │ │ ├── Box.swift
│ │ │ ├── CallbackQueue.swift
│ │ │ ├── Delegate.swift
│ │ │ ├── ExtensionHelpers.swift
│ │ │ ├── Result.swift
│ │ │ ├── Runtime.swift
│ │ │ ├── SizeExtensions.swift
│ │ │ └── String+MD5.swift
│ │ │ └── Views
│ │ │ ├── AnimatedImageView.swift
│ │ │ └── Indicator.swift
│ ├── Local Podspecs
│ │ └── JXPhotoBrowser.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ │ └── project.pbxproj
│ ├── SDWebImage
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── SDWebImage
│ │ │ ├── Core
│ │ │ │ ├── NSButton+WebCache.h
│ │ │ │ ├── NSButton+WebCache.m
│ │ │ │ ├── NSData+ImageContentType.h
│ │ │ │ ├── NSData+ImageContentType.m
│ │ │ │ ├── NSImage+Compatibility.h
│ │ │ │ ├── NSImage+Compatibility.m
│ │ │ │ ├── SDAnimatedImage.h
│ │ │ │ ├── SDAnimatedImage.m
│ │ │ │ ├── SDAnimatedImagePlayer.h
│ │ │ │ ├── SDAnimatedImagePlayer.m
│ │ │ │ ├── SDAnimatedImageRep.h
│ │ │ │ ├── SDAnimatedImageRep.m
│ │ │ │ ├── SDAnimatedImageView+WebCache.h
│ │ │ │ ├── SDAnimatedImageView+WebCache.m
│ │ │ │ ├── SDAnimatedImageView.h
│ │ │ │ ├── SDAnimatedImageView.m
│ │ │ │ ├── SDCallbackQueue.h
│ │ │ │ ├── SDCallbackQueue.m
│ │ │ │ ├── SDDiskCache.h
│ │ │ │ ├── SDDiskCache.m
│ │ │ │ ├── SDGraphicsImageRenderer.h
│ │ │ │ ├── SDGraphicsImageRenderer.m
│ │ │ │ ├── SDImageAPNGCoder.h
│ │ │ │ ├── SDImageAPNGCoder.m
│ │ │ │ ├── SDImageAWebPCoder.h
│ │ │ │ ├── SDImageAWebPCoder.m
│ │ │ │ ├── SDImageCache.h
│ │ │ │ ├── SDImageCache.m
│ │ │ │ ├── SDImageCacheConfig.h
│ │ │ │ ├── SDImageCacheConfig.m
│ │ │ │ ├── SDImageCacheDefine.h
│ │ │ │ ├── SDImageCacheDefine.m
│ │ │ │ ├── SDImageCachesManager.h
│ │ │ │ ├── SDImageCachesManager.m
│ │ │ │ ├── SDImageCoder.h
│ │ │ │ ├── SDImageCoder.m
│ │ │ │ ├── SDImageCoderHelper.h
│ │ │ │ ├── SDImageCoderHelper.m
│ │ │ │ ├── SDImageCodersManager.h
│ │ │ │ ├── SDImageCodersManager.m
│ │ │ │ ├── SDImageFrame.h
│ │ │ │ ├── SDImageFrame.m
│ │ │ │ ├── SDImageGIFCoder.h
│ │ │ │ ├── SDImageGIFCoder.m
│ │ │ │ ├── SDImageGraphics.h
│ │ │ │ ├── SDImageGraphics.m
│ │ │ │ ├── SDImageHEICCoder.h
│ │ │ │ ├── SDImageHEICCoder.m
│ │ │ │ ├── SDImageIOAnimatedCoder.h
│ │ │ │ ├── SDImageIOAnimatedCoder.m
│ │ │ │ ├── SDImageIOCoder.h
│ │ │ │ ├── SDImageIOCoder.m
│ │ │ │ ├── SDImageLoader.h
│ │ │ │ ├── SDImageLoader.m
│ │ │ │ ├── SDImageLoadersManager.h
│ │ │ │ ├── SDImageLoadersManager.m
│ │ │ │ ├── SDImageTransformer.h
│ │ │ │ ├── SDImageTransformer.m
│ │ │ │ ├── SDMemoryCache.h
│ │ │ │ ├── SDMemoryCache.m
│ │ │ │ ├── SDWebImageCacheKeyFilter.h
│ │ │ │ ├── SDWebImageCacheKeyFilter.m
│ │ │ │ ├── SDWebImageCacheSerializer.h
│ │ │ │ ├── SDWebImageCacheSerializer.m
│ │ │ │ ├── SDWebImageCompat.h
│ │ │ │ ├── SDWebImageCompat.m
│ │ │ │ ├── SDWebImageDefine.h
│ │ │ │ ├── SDWebImageDefine.m
│ │ │ │ ├── SDWebImageDownloader.h
│ │ │ │ ├── SDWebImageDownloader.m
│ │ │ │ ├── SDWebImageDownloaderConfig.h
│ │ │ │ ├── SDWebImageDownloaderConfig.m
│ │ │ │ ├── SDWebImageDownloaderDecryptor.h
│ │ │ │ ├── SDWebImageDownloaderDecryptor.m
│ │ │ │ ├── SDWebImageDownloaderOperation.h
│ │ │ │ ├── SDWebImageDownloaderOperation.m
│ │ │ │ ├── SDWebImageDownloaderRequestModifier.h
│ │ │ │ ├── SDWebImageDownloaderRequestModifier.m
│ │ │ │ ├── SDWebImageDownloaderResponseModifier.h
│ │ │ │ ├── SDWebImageDownloaderResponseModifier.m
│ │ │ │ ├── SDWebImageError.h
│ │ │ │ ├── SDWebImageError.m
│ │ │ │ ├── SDWebImageIndicator.h
│ │ │ │ ├── SDWebImageIndicator.m
│ │ │ │ ├── SDWebImageManager.h
│ │ │ │ ├── SDWebImageManager.m
│ │ │ │ ├── SDWebImageOperation.h
│ │ │ │ ├── SDWebImageOperation.m
│ │ │ │ ├── SDWebImageOptionsProcessor.h
│ │ │ │ ├── SDWebImageOptionsProcessor.m
│ │ │ │ ├── SDWebImagePrefetcher.h
│ │ │ │ ├── SDWebImagePrefetcher.m
│ │ │ │ ├── SDWebImageTransition.h
│ │ │ │ ├── SDWebImageTransition.m
│ │ │ │ ├── UIButton+WebCache.h
│ │ │ │ ├── UIButton+WebCache.m
│ │ │ │ ├── UIImage+ExtendedCacheData.h
│ │ │ │ ├── UIImage+ExtendedCacheData.m
│ │ │ │ ├── UIImage+ForceDecode.h
│ │ │ │ ├── UIImage+ForceDecode.m
│ │ │ │ ├── UIImage+GIF.h
│ │ │ │ ├── UIImage+GIF.m
│ │ │ │ ├── UIImage+MemoryCacheCost.h
│ │ │ │ ├── UIImage+MemoryCacheCost.m
│ │ │ │ ├── UIImage+Metadata.h
│ │ │ │ ├── UIImage+Metadata.m
│ │ │ │ ├── UIImage+MultiFormat.h
│ │ │ │ ├── UIImage+MultiFormat.m
│ │ │ │ ├── UIImage+Transform.h
│ │ │ │ ├── UIImage+Transform.m
│ │ │ │ ├── UIImageView+HighlightedWebCache.h
│ │ │ │ ├── UIImageView+HighlightedWebCache.m
│ │ │ │ ├── UIImageView+WebCache.h
│ │ │ │ ├── UIImageView+WebCache.m
│ │ │ │ ├── UIView+WebCache.h
│ │ │ │ ├── UIView+WebCache.m
│ │ │ │ ├── UIView+WebCacheOperation.h
│ │ │ │ ├── UIView+WebCacheOperation.m
│ │ │ │ ├── UIView+WebCacheState.h
│ │ │ │ └── UIView+WebCacheState.m
│ │ │ └── Private
│ │ │ │ ├── NSBezierPath+SDRoundedCorners.h
│ │ │ │ ├── NSBezierPath+SDRoundedCorners.m
│ │ │ │ ├── SDAssociatedObject.h
│ │ │ │ ├── SDAssociatedObject.m
│ │ │ │ ├── SDAsyncBlockOperation.h
│ │ │ │ ├── SDAsyncBlockOperation.m
│ │ │ │ ├── SDDeviceHelper.h
│ │ │ │ ├── SDDeviceHelper.m
│ │ │ │ ├── SDDisplayLink.h
│ │ │ │ ├── SDDisplayLink.m
│ │ │ │ ├── SDFileAttributeHelper.h
│ │ │ │ ├── SDFileAttributeHelper.m
│ │ │ │ ├── SDImageAssetManager.h
│ │ │ │ ├── SDImageAssetManager.m
│ │ │ │ ├── SDImageCachesManagerOperation.h
│ │ │ │ ├── SDImageCachesManagerOperation.m
│ │ │ │ ├── SDImageFramePool.h
│ │ │ │ ├── SDImageFramePool.m
│ │ │ │ ├── SDImageIOAnimatedCoderInternal.h
│ │ │ │ ├── SDInternalMacros.h
│ │ │ │ ├── SDInternalMacros.m
│ │ │ │ ├── SDWeakProxy.h
│ │ │ │ ├── SDWeakProxy.m
│ │ │ │ ├── SDWebImageTransitionInternal.h
│ │ │ │ ├── SDmetamacros.h
│ │ │ │ ├── UIColor+SDHexString.h
│ │ │ │ └── UIColor+SDHexString.m
│ │ └── WebImage
│ │ │ ├── PrivacyInfo.xcprivacy
│ │ │ └── SDWebImage.h
│ └── Target Support Files
│ │ ├── JXPhotoBrowser
│ │ ├── JXPhotoBrowser-Info.plist
│ │ ├── JXPhotoBrowser-dummy.m
│ │ ├── JXPhotoBrowser-prefix.pch
│ │ ├── JXPhotoBrowser-umbrella.h
│ │ ├── JXPhotoBrowser.debug.xcconfig
│ │ ├── JXPhotoBrowser.modulemap
│ │ ├── JXPhotoBrowser.release.xcconfig
│ │ └── JXPhotoBrowser.xcconfig
│ │ ├── Kingfisher
│ │ ├── Kingfisher-Info.plist
│ │ ├── Kingfisher-dummy.m
│ │ ├── Kingfisher-prefix.pch
│ │ ├── Kingfisher-umbrella.h
│ │ ├── Kingfisher.debug.xcconfig
│ │ ├── Kingfisher.modulemap
│ │ ├── Kingfisher.release.xcconfig
│ │ ├── Kingfisher.xcconfig
│ │ └── ResourceBundle-Kingfisher-Kingfisher-Info.plist
│ │ ├── Pods-Example
│ │ ├── Pods-Example-Info.plist
│ │ ├── Pods-Example-acknowledgements.markdown
│ │ ├── Pods-Example-acknowledgements.plist
│ │ ├── Pods-Example-dummy.m
│ │ ├── Pods-Example-frameworks-Debug-input-files.xcfilelist
│ │ ├── Pods-Example-frameworks-Debug-output-files.xcfilelist
│ │ ├── Pods-Example-frameworks-Release-input-files.xcfilelist
│ │ ├── Pods-Example-frameworks-Release-output-files.xcfilelist
│ │ ├── Pods-Example-frameworks.sh
│ │ ├── Pods-Example-umbrella.h
│ │ ├── Pods-Example.debug.xcconfig
│ │ ├── Pods-Example.modulemap
│ │ └── Pods-Example.release.xcconfig
│ │ └── SDWebImage
│ │ ├── ResourceBundle-SDWebImage-SDWebImage-Info.plist
│ │ ├── SDWebImage-Info.plist
│ │ ├── SDWebImage-dummy.m
│ │ ├── SDWebImage-prefix.pch
│ │ ├── SDWebImage-umbrella.h
│ │ ├── SDWebImage.debug.xcconfig
│ │ ├── SDWebImage.modulemap
│ │ ├── SDWebImage.release.xcconfig
│ │ └── SDWebImage.xcconfig
└── Sources
│ ├── AppIconScreenShot.png
│ └── 图片浏览器.sketch
├── JXPhotoBrowser.podspec
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── JXPhotoBrowser
│ ├── JXPhotoBrowser.swift
│ ├── JXPhotoBrowserAnimatedTransitioning.swift
│ ├── JXPhotoBrowserCell.swift
│ ├── JXPhotoBrowserDefaultPageIndicator.swift
│ ├── JXPhotoBrowserFadeAnimator.swift
│ ├── JXPhotoBrowserImageCell.swift
│ ├── JXPhotoBrowserImageView.swift
│ ├── JXPhotoBrowserLog.swift
│ ├── JXPhotoBrowserNoneAnimator.swift
│ ├── JXPhotoBrowserNumberPageIndicator.swift
│ ├── JXPhotoBrowserPageIndicator.swift
│ ├── JXPhotoBrowserSmoothZoomAnimator.swift
│ ├── JXPhotoBrowserView.swift
│ ├── JXPhotoBrowserZoomAnimator.swift
│ └── JXPhotoBrowserZoomSupportedCell.swift
├── SwiftPMExample
├── SwiftPMExample.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
└── SwiftPMExample
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── SceneDelegate.swift
│ └── ViewController.swift
├── Version1.x.md
└── Version2.x.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | .build/
7 | *.pbxuser
8 | !default.pbxuser
9 | *.mode1v3
10 | !default.mode1v3
11 | *.mode2v3
12 | !default.mode2v3
13 | *.perspectivev3
14 | !default.perspectivev3
15 | xcuserdata/
16 | *.xccheckout
17 | profile
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 |
23 | # Bundler
24 | .bundle
25 |
26 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
27 | # Carthage/Checkouts
28 |
29 | Carthage/Build
30 |
31 | # We recommend against adding the Pods directory to your .gitignore. However
32 | # you should judge for yourself, the pros and cons are mentioned at:
33 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
34 | #
35 | # Note: if you ignore the Pods directory, make sure to uncomment
36 | # `pod install` in .travis.yml
37 | #
38 | # Pods/
39 |
--------------------------------------------------------------------------------
/Assets/Browser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Browser.png
--------------------------------------------------------------------------------
/Assets/Home.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Home.gif
--------------------------------------------------------------------------------
/Assets/Introduction.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Introduction.gif
--------------------------------------------------------------------------------
/Assets/Transition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Transition.png
--------------------------------------------------------------------------------
/Assets/gifImage.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/gifImage.gif
--------------------------------------------------------------------------------
/Assets/rawImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/rawImage.jpg
--------------------------------------------------------------------------------
/Assets/testwebp.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/testwebp.webp
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/26.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
15 | // Override point for customization after application launch.
16 | return true
17 | }
18 |
19 | // MARK: UISceneSession Lifecycle
20 |
21 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
22 | // Called when a new scene session is being created.
23 | // Use this method to select a configuration to create the new scene with.
24 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
25 | }
26 |
27 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
28 | // Called when the user discards a scene session.
29 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
30 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
31 | }
32 |
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadProApp_83.5pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadProApp_83.5pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@3x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@3x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@3x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@2x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@3x.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器store_1024pt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器store_1024pt.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_0.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "local_0.jpeg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_0.imageset/local_0.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_0.imageset/local_0.jpeg
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "local_1.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_1.imageset/local_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_1.imageset/local_1.png
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "local_2.jpeg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_2.imageset/local_2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_2.imageset/local_2.jpeg
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "local_3.jpeg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_3.imageset/local_3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_3.imageset/local_3.jpeg
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_4.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "local_4.jpeg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_4.imageset/local_4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_4.imageset/local_4.jpeg
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_5.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "local_5.jpeg",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/local_5.imageset/local_5.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_5.imageset/local_5.jpeg
--------------------------------------------------------------------------------
/Example/Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/Example/BaseCollectionViewCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseCollectionViewCell.swift
3 | // JXPhotoBrwoser_Example
4 | //
5 | // Created by JiongXing on 2018/10/14.
6 | // Copyright © 2018年 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class BaseCollectionViewCell: UICollectionViewCell {
12 | lazy var imageView: UIImageView = {
13 | let iv = UIImageView()
14 | iv.clipsToBounds = true
15 | iv.contentMode = .scaleAspectFill
16 | return iv
17 | }()
18 |
19 | override init(frame: CGRect) {
20 | super.init(frame: frame)
21 | contentView.addSubview(imageView)
22 | }
23 |
24 | override func layoutSubviews() {
25 | super.layoutSubviews()
26 | imageView.frame = contentView.bounds
27 | }
28 |
29 | required init?(coder aDecoder: NSCoder) {
30 | fatalError("init(coder:) has not been implemented")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Example/Example/DefaultPageIndicatorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DefaultPageIndicatorViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/12/16.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 | import SDWebImage
12 |
13 | class DefaultPageIndicatorViewController: BaseCollectionViewController {
14 |
15 | override class func name() -> String { "UIPageControl样式的页码指示器" }
16 | override class func remark() -> String { "举例如何使用UIPageControl样式的页码指示器" }
17 |
18 | override func makeDataSource() -> [ResourceModel] {
19 | makeNetworkDataSource()
20 | }
21 |
22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl {
25 | let url = URL(string: firstLevel)
26 | cell.imageView.sd_setImage(with: url, completed: nil)
27 | }
28 | return cell
29 | }
30 |
31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
32 | let browser = JXPhotoBrowser()
33 | browser.numberOfItems = {
34 | self.dataSource.count
35 | }
36 | browser.reloadCellAtIndex = { context in
37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) }
38 | let browserCell = context.cell as? JXPhotoBrowserImageCell
39 | browserCell?.index = context.index
40 | let collectionPath = IndexPath(item: context.index, section: indexPath.section)
41 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell
42 | let placeholder = collectionCell?.imageView.image
43 | browserCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder, options: [], completed: { (_, _, _, _) in
44 | browserCell?.setNeedsLayout()
45 | })
46 | }
47 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in
48 | let path = IndexPath(item: index, section: indexPath.section)
49 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell
50 | return cell?.imageView
51 | })
52 | // UIPageIndicator样式的页码指示器
53 | browser.pageIndicator = JXPhotoBrowserDefaultPageIndicator()
54 | browser.pageIndex = indexPath.item
55 | browser.show()
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Example/Example/ImageSmoothZoomViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LocalImageSmoothZoomViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/28.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 |
12 | class ImageSmoothZoomViewController: BaseCollectionViewController {
13 |
14 | override class func name() -> String { "更丝滑的Zoom转场动画" }
15 | override class func remark() -> String { "需要用户自己创建并提供转场视图,以及缩略图位置" }
16 |
17 | override func makeDataSource() -> [ResourceModel] {
18 | makeLocalDataSource()
19 | }
20 |
21 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
22 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
23 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) }
24 | // 等比拉伸,填满视图
25 | cell.imageView.contentMode = .scaleAspectFill
26 | return cell
27 | }
28 |
29 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
30 | let browser = JXPhotoBrowser()
31 | browser.numberOfItems = {
32 | self.dataSource.count
33 | }
34 | browser.reloadCellAtIndex = { context in
35 | let browserCell = context.cell as? JXPhotoBrowserImageCell
36 | let indexPath = IndexPath(item: context.index, section: indexPath.section)
37 | browserCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) }
38 | }
39 | // 更丝滑的Zoom动画
40 | browser.transitionAnimator = JXPhotoBrowserSmoothZoomAnimator(transitionViewAndFrame: { (index, destinationView) -> JXPhotoBrowserSmoothZoomAnimator.TransitionViewAndFrame? in
41 | let path = IndexPath(item: index, section: indexPath.section)
42 | guard let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell else {
43 | return nil
44 | }
45 | let image = cell.imageView.image
46 | let transitionView = UIImageView(image: image)
47 | transitionView.contentMode = cell.imageView.contentMode
48 | transitionView.clipsToBounds = true
49 | let thumbnailFrame = cell.imageView.convert(cell.imageView.bounds, to: destinationView)
50 | return (transitionView, thumbnailFrame)
51 | })
52 | browser.pageIndex = indexPath.item
53 | browser.show(method: .push(inNC: nil))
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Example/Example/ImageZoomViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ImageZoomViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/28.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 |
12 | class ImageZoomViewController: BaseCollectionViewController {
13 |
14 | override class func name() -> String { "Zoom转场动画" }
15 | override class func remark() -> String { "简单易用的缩放式转场动画,兼容缩略图与放大图存在差异"}
16 |
17 | override func makeDataSource() -> [ResourceModel] {
18 | makeLocalDataSource()
19 | }
20 |
21 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
22 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
23 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) }
24 | return cell
25 | }
26 |
27 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
28 | let browser = JXPhotoBrowser()
29 | browser.numberOfItems = {
30 | self.dataSource.count
31 | }
32 | browser.reloadCellAtIndex = { context in
33 | let browserCell = context.cell as? JXPhotoBrowserImageCell
34 | let indexPath = IndexPath(item: context.index, section: indexPath.section)
35 | browserCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) }
36 | }
37 | // 使用Zoom动画
38 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in
39 | let path = IndexPath(item: index, section: indexPath.section)
40 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell
41 | return cell?.imageView
42 | })
43 | browser.pageIndex = indexPath.item
44 | browser.show()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Example/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | PhotoBrowser
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSAllowsArbitraryLoads
28 |
29 |
30 | UIApplicationSceneManifest
31 |
32 | UIApplicationSupportsMultipleScenes
33 |
34 | UISceneConfigurations
35 |
36 | UIWindowSceneSessionRoleApplication
37 |
38 |
39 | UISceneConfigurationName
40 | Default Configuration
41 | UISceneDelegateClassName
42 | $(PRODUCT_MODULE_NAME).SceneDelegate
43 | UISceneStoryboardFile
44 | Main
45 |
46 |
47 |
48 |
49 | UILaunchStoryboardName
50 | LaunchScreen
51 | UIMainStoryboardFile
52 | Main
53 | UIRequiredDeviceCapabilities
54 |
55 | armv7
56 |
57 | UISupportedInterfaceOrientations
58 |
59 | UIInterfaceOrientationPortrait
60 | UIInterfaceOrientationLandscapeLeft
61 | UIInterfaceOrientationLandscapeRight
62 |
63 | UISupportedInterfaceOrientations~ipad
64 |
65 | UIInterfaceOrientationPortrait
66 | UIInterfaceOrientationPortraitUpsideDown
67 | UIInterfaceOrientationLandscapeLeft
68 | UIInterfaceOrientationLandscapeRight
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Example/Example/JXNamespace.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JXNamespace.swift
3 | // JXPhotoBrowser
4 | //
5 | // Created by JiongXing on 2018/10/14.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 类型协议
11 | public protocol JXTypeWrapperProtocol {
12 | associatedtype JXWrappedType
13 | var jxWrappedValue: JXWrappedType { get }
14 | init(value: JXWrappedType)
15 | }
16 |
17 | public struct JXNamespaceWrapper: JXTypeWrapperProtocol {
18 | public let jxWrappedValue: T
19 | public init(value: T) {
20 | self.jxWrappedValue = value
21 | }
22 | }
23 |
24 | /// 命名空间协议
25 | public protocol JXNamespaceWrappable {
26 | associatedtype JXWrappedType
27 | var jx: JXWrappedType { get }
28 | static var jx: JXWrappedType.Type { get }
29 | }
30 |
31 | extension JXNamespaceWrappable {
32 | public var jx: JXNamespaceWrapper {
33 | return JXNamespaceWrapper(value: self)
34 | }
35 |
36 | public static var jx: JXNamespaceWrapper.Type {
37 | return JXNamespaceWrapper.self
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Example/Example/KingfisherImageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KingfisherImageViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/28.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 | import Kingfisher
12 |
13 | class KingfisherImageViewController: BaseCollectionViewController {
14 |
15 | override class func name() -> String { "网络图片-Kingfisher" }
16 | override class func remark() -> String { "举例如何用Kingfisher加载网络图片" }
17 |
18 | override func makeDataSource() -> [ResourceModel] {
19 | makeNetworkDataSource()
20 | }
21 |
22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl {
25 | let url = URL(string: firstLevel)
26 | cell.imageView.kf.setImage(with: url)
27 | }
28 | return cell
29 | }
30 |
31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
32 | let browser = JXPhotoBrowser()
33 | browser.numberOfItems = {
34 | self.dataSource.count
35 | }
36 | browser.reloadCellAtIndex = { context in
37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) }
38 | let browserCell = context.cell as? JXPhotoBrowserImageCell
39 | let collectionPath = IndexPath(item: context.index, section: indexPath.section)
40 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell
41 | let placeholder = collectionCell?.imageView.image
42 | // 用 Kingfisher 加载
43 | browserCell?.imageView.kf.setImage(with: url, placeholder: placeholder)
44 | }
45 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in
46 | let path = IndexPath(item: index, section: indexPath.section)
47 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell
48 | return cell?.imageView
49 | })
50 | browser.pageIndex = indexPath.item
51 | browser.show()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Example/Example/LocalImageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LocalImageViewController.swift
3 | // JXPhotoBrwoser_Example
4 | //
5 | // Created by JiongXing on 2018/10/14.
6 | // Copyright © 2018年 CocoaPods. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 |
12 | class LocalImageViewController: BaseCollectionViewController {
13 |
14 | override class func name() -> String { "本地图片" }
15 | override class func remark() -> String { "最简单的场景,展示本地图片" }
16 |
17 | override func makeDataSource() -> [ResourceModel] {
18 | makeLocalDataSource()
19 | }
20 |
21 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
22 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
23 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) }
24 | return cell
25 | }
26 |
27 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
28 | // 实例化
29 | let browser = JXPhotoBrowser()
30 | // 浏览过程中实时获取数据总量
31 | browser.numberOfItems = {
32 | self.dataSource.count
33 | }
34 | // 刷新Cell数据。本闭包将在Cell完成位置布局后调用。
35 | browser.reloadCellAtIndex = { context in
36 | let browserCell = context.cell as? JXPhotoBrowserImageCell
37 | let indexPath = IndexPath(item: context.index, section: indexPath.section)
38 | browserCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) }
39 | }
40 | // 可指定打开时定位到哪一页
41 | browser.pageIndex = indexPath.item
42 | // 展示
43 | browser.show()
44 |
45 | // dismis回调
46 | browser.willDismiss = { _ in
47 | JXPhotoBrowserLog.low("即将dismiss!")
48 | return true
49 | }
50 | browser.didDismiss = { _ in
51 | JXPhotoBrowserLog.low("已经dismiss!")
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Example/Example/MoreDetailViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MoreDetailViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/26.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MoreDetailViewController: UIViewController {
12 |
13 | lazy var label: UILabel = {
14 | let lab = UILabel()
15 | lab.textColor = .black
16 | lab.text = "< 更多详情 >"
17 | lab.textAlignment = .center
18 | return lab
19 | }()
20 |
21 | override func viewDidLoad() {
22 | super.viewDidLoad()
23 | view.backgroundColor = .white
24 |
25 | view.addSubview(label)
26 | }
27 |
28 | override func viewWillLayoutSubviews() {
29 | super.viewWillLayoutSubviews()
30 | label.frame = view.bounds
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Example/Example/NumberPageIndicatorViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NumberPageIndicatorViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/12/16.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 | import SDWebImage
12 |
13 | class NumberPageIndicatorViewController: BaseCollectionViewController {
14 |
15 | override class func name() -> String { "数字样式的页码指示器" }
16 | override class func remark() -> String { "举例如何使用数字样式的页码指示器" }
17 |
18 | override func makeDataSource() -> [ResourceModel] {
19 | makeNetworkDataSource()
20 | }
21 |
22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl {
25 | let url = URL(string: firstLevel)
26 | cell.imageView.sd_setImage(with: url, completed: nil)
27 | }
28 | return cell
29 | }
30 |
31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
32 | let browser = JXPhotoBrowser()
33 | browser.numberOfItems = {
34 | self.dataSource.count
35 | }
36 | browser.reloadCellAtIndex = { context in
37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) }
38 | let browserCell = context.cell as? JXPhotoBrowserImageCell
39 | browserCell?.index = context.index
40 | let collectionPath = IndexPath(item: context.index, section: indexPath.section)
41 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell
42 | let placeholder = collectionCell?.imageView.image
43 | browserCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder, options: [], completed: { (_, _, _, _) in
44 | browserCell?.setNeedsLayout()
45 | })
46 | }
47 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in
48 | let path = IndexPath(item: index, section: indexPath.section)
49 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell
50 | return cell?.imageView
51 | })
52 | // 数字样式的页码指示器
53 | browser.pageIndicator = JXPhotoBrowserNumberPageIndicator()
54 | browser.pageIndex = indexPath.item
55 | browser.show()
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Example/Example/Photos.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7nzbz7j20ib0iek5j.jpg
7 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7nzbz7j20ib0iek5j.jpg
8 | (1)凡所有相,皆是虚妄,若见诸相非相,即见如来.
9 |
10 |
11 | http://wx1.sinaimg.cn/thumbnail/bfc243a3gy1febm7orgqfj20i80ht15x.jpg
12 | http://wx1.sinaimg.cn/large/bfc243a3gy1febm7orgqfj20i80ht15x.jpg
13 | (2)身是菩提树,心如明镜台,时时勤擦拭,莫使惹尘埃.
14 |
15 |
16 | http://wx1.sinaimg.cn/thumbnail/bfc243a3gy1febm7n9eorj20i60hsann.jpg
17 | http://wx1.sinaimg.cn/large/bfc243a3gy1febm7n9eorj20i60hsann.jpg
18 | (3)菩提本无树,名镜亦非台,本来无一物,何处惹尘埃.
19 |
20 |
21 | http://wx2.sinaimg.cn/thumbnail/bfc243a3gy1febm7pmnk7j20i70jidwo.jpg
22 | http://wx2.sinaimg.cn/large/bfc243a3gy1febm7pmnk7j20i70jidwo.jpg
23 | (4)一切有为法,如梦幻泡影。如露亦如电,应作如是观.
24 |
25 |
26 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7qjop4j20i00hw4c6.jpg
27 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7qjop4j20i00hw4c6.jpg
28 | (5)色不异空,空不异色,色即是空,空即是色.
29 |
30 |
31 | http://wx4.sinaimg.cn/thumbnail/bfc243a3gy1febm7rncxaj20ek0i74dv.jpg
32 | http://wx4.sinaimg.cn/large/bfc243a3gy1febm7rncxaj20ek0i74dv.jpg
33 | (6)一切有为法,如梦幻泡影。如露亦如电,应作如是观.
34 |
35 |
36 | http://wx2.sinaimg.cn/thumbnail/bfc243a3gy1febm7sdk4lj20ib0i714u.jpg
37 | http://wx2.sinaimg.cn/large/bfc243a3gy1febm7sdk4lj20ib0i714u.jpg
38 | (7)烦恼即菩提.
39 |
40 |
41 | http://wx4.sinaimg.cn/thumbnail/bfc243a3gy1febm7tekewj20i20i4aoy.jpg
42 | http://wx4.sinaimg.cn/large/bfc243a3gy1febm7tekewj20i20i4aoy.jpg
43 | (8)过去心不可得,现在心不可得,未来心不可得.
44 |
45 |
46 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7usmc8j20i543zngx.jpg
47 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7usmc8j20i543zngx.jpg
48 | (9)纵使经百劫,所作业不亡,因缘会遇时,果报还自受.
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Example/Example/ResourceModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ResourceModel.swift
3 | // JXPhotoBrowser
4 | //
5 | // Created by JiongXing on 2019/11/20.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /// 视像资源模型
12 | class ResourceModel {
13 | /// 第一级资源
14 | var firstLevelUrl: String?
15 | /// 第二级资源
16 | var secondLevelUrl: String?
17 | /// 第三级资源
18 | var thirdLevelUrl: String?
19 | /// 本地资源,资源名
20 | var localName: String?
21 | /// 备注配文
22 | var remark: String?
23 | }
24 |
--------------------------------------------------------------------------------
/Example/Example/SDWebImageViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SDWebImageViewController.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/28.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import JXPhotoBrowser
11 | import SDWebImage
12 |
13 | class SDWebImageViewController: BaseCollectionViewController {
14 |
15 | override class func name() -> String { "网络图片-SDWebImage" }
16 | override class func remark() -> String { "举例如何用SDWebImage加载网络图片" }
17 |
18 | override func makeDataSource() -> [ResourceModel] {
19 | makeNetworkDataSource()
20 | }
21 |
22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath)
24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl {
25 | let url = URL(string: firstLevel)
26 | cell.imageView.sd_setImage(with: url, completed: nil)
27 | }
28 | return cell
29 | }
30 |
31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) {
32 | let browser = JXPhotoBrowser()
33 | browser.numberOfItems = {
34 | self.dataSource.count
35 | }
36 | browser.reloadCellAtIndex = { context in
37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) }
38 | let browserCell = context.cell as? JXPhotoBrowserImageCell
39 | browserCell?.index = context.index
40 | let collectionPath = IndexPath(item: context.index, section: indexPath.section)
41 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell
42 | let placeholder = collectionCell?.imageView.image
43 | // 用 SDWebImage 加载
44 | browserCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder)
45 | }
46 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in
47 | let path = IndexPath(item: index, section: indexPath.section)
48 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell
49 | return cell?.imageView
50 | })
51 | browser.pageIndex = indexPath.item
52 | browser.show()
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Example/Example/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SceneDelegate.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/11/26.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
12 |
13 | var window: UIWindow?
14 |
15 |
16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
20 | guard let _ = (scene as? UIWindowScene) else { return }
21 | }
22 |
23 | func sceneDidDisconnect(_ scene: UIScene) {
24 | // Called as the scene is being released by the system.
25 | // This occurs shortly after the scene enters the background, or when its session is discarded.
26 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
28 | }
29 |
30 | func sceneDidBecomeActive(_ scene: UIScene) {
31 | // Called when the scene has moved from an inactive state to an active state.
32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
33 | }
34 |
35 | func sceneWillResignActive(_ scene: UIScene) {
36 | // Called when the scene will move from an active state to an inactive state.
37 | // This may occur due to temporary interruptions (ex. an incoming phone call).
38 | }
39 |
40 | func sceneWillEnterForeground(_ scene: UIScene) {
41 | // Called as the scene transitions from the background to the foreground.
42 | // Use this method to undo the changes made on entering the background.
43 | }
44 |
45 | func sceneDidEnterBackground(_ scene: UIScene) {
46 | // Called as the scene transitions from the foreground to the background.
47 | // Use this method to save data, release shared resources, and store enough scene-specific state information
48 | // to restore the scene back to its current state.
49 | }
50 |
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/Example/Example/UICollectionView+JX.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UICollectionView+JX.swift
3 | // JXPhotoBrowser
4 | //
5 | // Created by JiongXing on 2018/10/14.
6 | //
7 |
8 | import UIKit
9 |
10 | extension UICollectionView: JXNamespaceWrappable {}
11 |
12 | extension JXTypeWrapperProtocol where JXWrappedType == UICollectionView {
13 |
14 | /// 注册Cell
15 | public func registerCell(_ type: T.Type) {
16 | let identifier = String(describing: type.self)
17 | jxWrappedValue.register(type, forCellWithReuseIdentifier: identifier)
18 | }
19 |
20 | /// 取重用Cell
21 | public func dequeueReusableCell(_ type: T.Type, for indexPath: IndexPath) -> T {
22 | let identifier = String(describing: type.self)
23 | guard let cell = jxWrappedValue.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? T else {
24 | fatalError("\(type.self) was not registered")
25 | }
26 | return cell
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Example/Example/UITableView+JX.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UITableView+JX.swift
3 | // JXPhotoBrowser
4 | //
5 | // Created by JiongXing on 2019/11/20.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UITableView: JXNamespaceWrappable {}
12 |
13 | extension JXTypeWrapperProtocol where JXWrappedType == UITableView {
14 |
15 | /// 注册Cell
16 | public func registerCell(_ type: T.Type) {
17 | let identifier = String(describing: type.self)
18 | jxWrappedValue.register(type, forCellReuseIdentifier: identifier)
19 | }
20 |
21 | /// 取重用Cell
22 | public func dequeueReusableCell(_ type: T.Type) -> T {
23 | let identifier = String(describing: type.self)
24 | guard let cell = jxWrappedValue.dequeueReusableCell(withIdentifier: identifier) as? T else {
25 | fatalError("\(type.self) was not registered")
26 | }
27 | return cell
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Example/Example/VideoCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // VideoCell.swift
3 | // Example
4 | //
5 | // Created by JiongXing on 2019/12/13.
6 | // Copyright © 2019 JiongXing. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 | import AVFoundation
12 | import JXPhotoBrowser
13 |
14 | class VideoCell: UIView, JXPhotoBrowserCell {
15 |
16 | weak var photoBrowser: JXPhotoBrowser?
17 |
18 | lazy var player = AVPlayer()
19 | lazy var playerLayer = AVPlayerLayer(player: player)
20 |
21 | static func generate(with browser: JXPhotoBrowser) -> Self {
22 | let instance = Self.init(frame: .zero)
23 | instance.photoBrowser = browser
24 | return instance
25 | }
26 |
27 | required override init(frame: CGRect) {
28 | super.init(frame: .zero)
29 | backgroundColor = .black
30 |
31 | let tap = UITapGestureRecognizer(target: self, action: #selector(click))
32 | addGestureRecognizer(tap)
33 |
34 | layer.addSublayer(playerLayer)
35 | }
36 |
37 | required init?(coder: NSCoder) {
38 | fatalError("init(coder:) has not been implemented")
39 | }
40 |
41 | override func layoutSubviews() {
42 | super.layoutSubviews()
43 | playerLayer.frame = bounds
44 | }
45 |
46 | @objc private func click() {
47 | photoBrowser?.dismiss()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Example/Example/video_0.MP4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/video_0.MP4
--------------------------------------------------------------------------------
/Example/Example/video_1.MP4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/video_1.MP4
--------------------------------------------------------------------------------
/Example/Example/video_2.MP4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/video_2.MP4
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 |
2 | platform :ios, '13.0'
3 |
4 | target 'Example' do
5 | # Comment the next line if you don't want to use dynamic frameworks
6 | use_frameworks!
7 |
8 | # Pods for Example
9 | pod 'JXPhotoBrowser', :path => '../'
10 | pod 'Kingfisher'
11 | pod 'SDWebImage'
12 |
13 | post_install do |installer|
14 | installer.pods_project.targets.each do |target|
15 | target.build_configurations.each do |config|
16 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
17 | end
18 | end
19 | end
20 |
21 | end
22 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - JXPhotoBrowser (3.1.5)
3 | - Kingfisher (7.10.2)
4 | - SDWebImage (5.18.10):
5 | - SDWebImage/Core (= 5.18.10)
6 | - SDWebImage/Core (5.18.10)
7 |
8 | DEPENDENCIES:
9 | - JXPhotoBrowser (from `../`)
10 | - Kingfisher
11 | - SDWebImage
12 |
13 | SPEC REPOS:
14 | trunk:
15 | - Kingfisher
16 | - SDWebImage
17 |
18 | EXTERNAL SOURCES:
19 | JXPhotoBrowser:
20 | :path: "../"
21 |
22 | SPEC CHECKSUMS:
23 | JXPhotoBrowser: e0dad01805e85c317ac8844ce793f7935fa918ed
24 | Kingfisher: 99edc495d3b7607e6425f0d6f6847b2abd6d716d
25 | SDWebImage: fc8f2d48bbfd72ef39d70e981bd24a3f3be53fec
26 |
27 | PODFILE CHECKSUM: 92abaea6b2d28b30ee834a17b1a190e01247e20d
28 |
29 | COCOAPODS: 1.14.2
30 |
--------------------------------------------------------------------------------
/Example/Pods/Kingfisher/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 Wei Wang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Example/Pods/Kingfisher/Sources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyAccessedAPITypes
6 |
7 |
8 | NSPrivacyAccessedAPIType
9 | NSPrivacyAccessedAPICategoryFileTimestamp
10 | NSPrivacyAccessedAPITypeReasons
11 |
12 | C617.1
13 |
14 |
15 |
16 | NSPrivacyTracking
17 |
18 | NSPrivacyTrackingDomains
19 |
20 |
21 | NSPrivacyCollectedDataTypes
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/Pods/Kingfisher/Sources/Utility/Box.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Box.swift
3 | // Kingfisher
4 | //
5 | // Created by Wei Wang on 2018/3/17.
6 | // Copyright (c) 2019 Wei Wang
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | import Foundation
27 |
28 | class Box {
29 | var value: T
30 |
31 | init(_ value: T) {
32 | self.value = value
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Example/Pods/Kingfisher/Sources/Utility/Result.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Result.swift
3 | // Kingfisher
4 | //
5 | // Created by onevcat on 2018/09/22.
6 | //
7 | // Copyright (c) 2019 Wei Wang
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | import Foundation
28 |
29 | // These helper methods are not public since we do not want them to be exposed or cause any conflicting.
30 | // However, they are just wrapper of `ResultUtil` static methods.
31 | extension Result where Failure: Error {
32 |
33 | /// Evaluates the given transform closures to create a single output value.
34 | ///
35 | /// - Parameters:
36 | /// - onSuccess: A closure that transforms the success value.
37 | /// - onFailure: A closure that transforms the error value.
38 | /// - Returns: A single `Output` value.
39 | func match