/PhotoBrowser

Elegant photo browser in Swift. 图片浏览器,类似微信

Primary LanguageSwiftMIT LicenseMIT

JXPhotoBrowser

Version License Platform

Features

  • 支持本地图片
  • 支持初始图、高清图和原图三个级别
  • 支持GIF格式
  • 支持WebP格式
  • 支持Fade渐变转场动画
  • 支持Zoom缩放转场动画
  • 支持下滑手势关闭浏览器
  • 支持单击、双击、放大缩小、长按
  • 支持屏幕旋转
  • 支持修改数据源,重载数据
  • 支持代码调用图片切换
  • 支持继承图片浏览器
  • 支持自定义页视图Cell
  • 支持自定义图片加载器
  • 提供了基于Kingfisher的图片加载器实现
  • 提供了基于KingfisherWebP的WebP图片加载器实现
  • 提供了光点型的页码指示器的实现
  • 提供了数字型的页码指示器的实现
  • 提供了图片加载进度指示器的实现
  • 提供了查看原图按钮的实现
  • 提供了多种数据源代理、视图代理和转场动画代理的实现,自由搭配选用
  • 纯视频、视频与图片混合(待开发)

Change Log

Version 2.1.2

2018/12/07

  • 修复显示长图时可能发生的交互BUG

Version 2.1.1

2018/11/29

  • 优化横屏模式的显示效果,横屏时显示全图

Version 2.1.0

2018/10/27

  • 现可通过泛型的方式向三种默认的数据源指定要使用的Cell,并增加一个泛型方法在复用时直接返回所设置的Cell。
  • 支持修改数据源,重载数据
  • 支持代码调用图片切换
  • 对传入的pageIndex保护,越界时自动修正为安全值。
  • 可禁止添加长按手势。
  • JXNetworkingDataSourceJXRawImageDataSource的初始化方法中,localImage重命名为placeholder,表意更清晰。
  • 删除JXPhotoBrowserBaseCellsetupViews方法,子类应重写init(frame: CGRect)方法,然后作进一步初始化。

Version 2.0.x

2018/10/18

  • 重新设计了接口,使用起来更简单易懂。
  • 进行了大规模重构,代码更优雅,更易扩展,更易维护。
  • 注意如果是从1.x版本升级上来的,遇到无法编译情况,请清除Xcode的Derived Data

Version 1.6.1

1.x版本不再更新功能,若要使用,可参考:Version_1.x

更多

查看更多日志:CHANGELOG

Requirements

  • iOS 9.0
  • Swift 4.2
  • Xcode 10
  • 如需要用在Swift4.2之下的项目使用,请自行修改为相应Swift版本的语法。
  • 改为Swift4.0或4.1的语法,修改的地方只有几处,工作量不大。

Installation

CocoaPods

更新你的本地仓库以同步最新版本

pod repo update

在你项目的Podfile中配置

pod 'JXPhotoBrowser'

如果需要加载WebP图片,则引入subspec

pod 'JXPhotoBrowser/KingfisherWebP'

手动导入

  1. 请把Source/Core下的所有文件拷贝到你的项目。
  2. 如果需要使用Kingfisher来加载网络图片,就把Source/Kingfisher下的文件也拷贝到你的项目,并导入Kingfisher库。
  3. 如果需要加载WebP图片,就把Source/KingfisherWebP下的文件也拷贝到你的项目,并导入KingfisherWebP库。

Usage

初始化

创建图片浏览器需要三个参数,分别是数据源、视图代理、转场代理。 其中数据源是必须自行创建并传入,而视图代理和转场代理是可选的,它们有默认值。

open class JXPhotoBrowser: UIViewController {
    public init(dataSource: JXPhotoBrowserDataSource,
                delegate: JXPhotoBrowserDelegate = JXPhotoBrowserBaseDelegate(),
                transDelegate: JXPhotoBrowserTransitioningDelegate = JXPhotoBrowserFadeTransitioning())
}

打开图片浏览器

打开图片浏览器之前,需要指定所浏览图片的序号:

photoBrowser.pageIndex = selectedIndex

然后通过UIViewControllerpresent方法打开:

viewController.present(photoBrowser, animated: true, completion: nil)

还有更简洁的代码是这样:

JXPhotoBrowser(dataSource: dataSource).show(pageIndex: indexPath.item)

本地图片

项目例子展示了如何浏览本地图片:

// 数据源
let dataSource = JXLocalDataSource(numberOfItems: {
    // 共有多少项
    return self.dataSource.count
}, localImage: { index -> UIImage? in
    // 每一项的图片对象
    return self.dataSource[index].localName.flatMap({ name -> UIImage? in
        return UIImage(named: name)
    })
})
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource).show(pageIndex: indexPath.item)

动作事件

默认实现了单击、双击、拖拽、长按事件。可以给视图代理设置长按事件的回调:

// 视图代理
let delegate = JXPhotoBrowserBaseDelegate()
// 长按事件
delegate.longPressedCallback = { browser, index, image, gesture in
	// ...
}
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate: delegate).show(pageIndex: indexPath.item)

光点型页码指示器

可通过自定义视图代理来增加控件

// 视图代理,实现了光点型页码指示器
let delegate = JXDefaultPageControlDelegate()
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate:delegate).show(pageIndex: indexPath.item)

数字型页码指示器

// 视图代理,实现了数字型页码指示器
let delegate = JXNumberPageControlDelegate()
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate:delegate).show(pageIndex: indexPath.item)

转场动画

打开JXPhotoBrowser时,默认使用的转场动画是Fade渐变型的,如果想要Zoom缩张型,需要返回动画起始/结束位置给Zoom动画代理。 本框架提供了两种方案,你可选择返回起始/结束视图,或选择返回起始/结束坐标。

// 返回起始/结束 视图
let trans = JXPhotoBrowserZoomTransitioning { (browser, index, view) -> UIView? in
    let indexPath = IndexPath(item: index, section: 0)
    return collectionView.cellForItem(at: indexPath)
}
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate: delegate, transDelegate: trans)
	.show(pageIndex: indexPath.item)
// 返回起始/结束 位置
let trans = JXPhotoBrowserZoomTransitioning { (browser, index, view) -> CGRect? in
    let indexPath = IndexPath(item: index, section: 0)
    if let cell = collectionView.cellForItem(at: indexPath) {
        return cell.convert(cell.bounds, to: view)
    }
    return nil
}
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate: delegate, transDelegate: trans)
	.show(pageIndex: indexPath.item)

网络图片-两级:缩略图和高清图

加载网络图片需要指定网图加载器,本框架以Kingfisher为基础实现加载器。 如果你不想使用Kingfisher,可自己实现一个网图加载器。 要加载网络图片,需要使用网络资源数据源,本框架实现了一个NetworkingDataSource

// 网图加载器
let loader = JXPhotoBrowser.KingfisherLoader()
// 数据源
let dataSource = JXNetworkingDataSource(photoLoader: loader, numberOfItems: { () -> Int in
    return self.dataSource.count
}, placeholder: { index -> UIImage? in
    let cell = collectionView.cellForItem(at: indexPath) as? BaseCollectionViewCell
    return cell?.imageView.image
}) { index -> String? in
    return self.dataSource[index].secondLevelUrl
}
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate: delegate, transDelegate: trans)
    .show(pageIndex: indexPath.item)

网络图片-三级:缩略图、高清图和原图

如果资源有三个级别,需要有查看原图功能的话,本框架也实现了一个数据源RawImageDataSource

// 网图加载器
let loader = JXPhotoBrowser.KingfisherLoader()
// 数据源
let dataSource = JXRawImageDataSource(photoLoader: loader, numberOfItems: { () -> Int in
    return self.dataSource.count
}, placeholder: { index -> UIImage? in
    let cell = collectionView.cellForItem(at: indexPath) as? BaseCollectionViewCell
    return cell?.imageView.image
}, autoloadURLString: { index -> String? in
    return self.dataSource[index].secondLevelUrl
}) { index -> String? in
    return self.dataSource[index].thirdLevelUrl
}
// 打开浏览器
JXPhotoBrowser(dataSource: dataSource, delegate: delegate, transDelegate: trans)
    .show(pageIndex: indexPath.item)

GIF图片

Kingfisher已支持加载GIF格式,所以可直接使用KingfisherLoader

// 网图加载器
let loader = JXKingfisherLoader()
let dataSource = JXPhotoBrowser.NetworkingDataSource(photoLoader: loader, ...)

WebP图片

要加载WebP图片,本框架实现了一个网图加载器KingfisherWebPLoader,需要在podfile文件引入subspec:

pod 'JXPhotoBrowser/KingfisherWebP'

然后使用它作为网图加载器:

// 网图加载器,WebP加载器
let loader = JXKingfisherWebPLoader()
let dataSource = JXPhotoBrowser.NetworkingDataSource(photoLoader: loader, ...)

自定义Cell

如果需要对页视图作更多自定义,可继承JXPhotoBrowserBaseCell创建你的Cell。 然后在创建数据源代理时,通过泛型的方式设置你的Cell:

// 数据源,通过泛型指定使用的<Cell>
let dataSource = JXNetworkingDataSource<CustomCell>(...)
// Cell复用回调
dataSource.configReusableCell { (cell, index) in
    // 给复用Cell刷新数据
}

禁用长按手势

可通过自定义Cell重写isNeededLongPressGesture属性以禁止:

class CustomCell: JXPhotoBrowserBaseCell {
    /// 是否需要添加长按手势。返回`false`即可避免添加长按手势
    override var isNeededLongPressGesture: Bool {
        return false
    }
}

常见问题

Archive 打包错误

如果出现:

While deserializing SIL vtable for ...
abort trap 6

请升级你的工程到Swift4.2,即可解决。

Install 错误:Error installing libwebp

谷歌家的libwebp是放在他家网上的,pod 'libwebp'的源指向了谷歌域名的地址,解决办法一是翻墙,二是把本地 repo 源改为放在 Github 上的镜像:

  1. pod search libwebp 看看有哪些版本,记住你想 install 的版本号,一般用最新的就行,比如 1.0.0。
  2. pod repo 查看 master 的 path,进入目录搜索 libwebp,进入 libwebp -> 1.0.0,找到libwebp.podspec.json
  3. 打开libwebp.podspec.json,修改 source 地址:
"source": {
    "git": "https://github.com/webmproject/libwebp",
    "tag": "v1.0.0
  },
  1. 回到你的项目目录,可以愉快地pod install了~

初版实现思路

记录了初版实现思路:ARTICLE

感谢

若使用过程中有任何问题,请issues我。 ^_^