封装了一个图片浏览器,实现了图片的浏览,缩放,支持多张图片的浏览缩放,保存到相册等功能
1.图片浏览,根据图片的大小适应,浏览长图
2.多张图片左右滑动浏览
3.图片的缩放
4.播放gif图片
1.使用UICollectionView作为图片浏览的承载控制器
2.自定义cell显示图片,
3.使用UIScrollerView作为最底层视图
4.使用UIImageView显示图片
5.使用Kingfisher加载网络图片
6.使用UIImageWriteToSavedPhotosAlbum保存图片到相册
7.使用SVProgressHUD作为保存图片成功的提示
8.使用snapkit作为layout的布局约束
为什么在cell中要使用UIScrollerView
1.显示长图片,可以上下滑动浏览图片
2.使用UIScrollerView的代理方法实现图片的缩放功能,
3.使用UIScrollerView的代理方法实现监听图片缩放完成后的居中操作
代码文件下载地址
效果演示
使用方法
///index为当前点击了图片数组中的第几张图片,Urls为图片Url地址数组
**Urls必须传入为https或者http的图片地址数组,**
let vc = PictureVisitControl(index: index.row, Urls: Urls as! [URL])
present(vc, animated: true, completion: nil)
源码
import UIKit
import SVProgressHUD
class PictureVisitControl: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
}
var currentIndex:Int?
var pictureUrls:[URL]?
init(index:Int,Urls:[URL]) {
//先初始化本类属性,在初始化父类
currentIndex = index
pictureUrls = Urls
super.init(nibName: nil, bundle: nil)
setUpUI()
view.backgroundColor = .white
}
private func setUpUI(){
view.addSubview(collectionView)
view.addSubview(closebtn)
view.addSubview(SaveBtn)
//设置数据源
collectionView.dataSource = self;
collectionView.register(PictureVisitControlCell.self, forCellWithReuseIdentifier: "item")
setlayoutContains()
}
private func setlayoutContains(){
closebtn.snp.makeConstraints { (make) in
make.bottom.equalTo(self.view.snp.bottom).offset(-30)
make.left.equalTo(20)
make.width.equalTo(100)
make.height.equalTo(35)
}
SaveBtn.snp.makeConstraints { (make) in
make.bottom.equalTo(self.view.snp.bottom).offset(-30)
make.right.equalTo(self.view.snp.right).offset(-20)
make.width.equalTo(100)
make.height.equalTo(35)
}
collectionView.snp.makeConstraints { (make) in
make.top.left.bottom.right.equalTo(0)
}
}
@objc private func closeAction(){
dismiss(animated: true, completion: nil)
}
@objc private func SaveAction(){
let index = collectionView.indexPathsForVisibleItems.last!
let cell:PictureVisitControlCell = collectionView.cellForItem(at: index) as! PictureVisitControlCell
//保存图片
let img = cell.IMg.image
UIImageWriteToSavedPhotosAlbum(img!, self, #selector(image(image:didFinishSavingWithError:contextInfo:)), nil)
// - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
}
@objc func image(image:UIImage,didFinishSavingWithError error:NSError?,contextInfo:AnyObject){
if error != nil {
SVProgressHUD.showError(withStatus: "保存失败")
}else
{
SVProgressHUD.showSuccess(withStatus: "保存成功")
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private lazy var collectionView:UICollectionView = UICollectionView(frame:CGRect.zero, collectionViewLayout: PicturePrepareLayout())
private lazy var closebtn:UIButton = {
let btn = UIButton()
btn.setTitle("关闭", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.backgroundColor = UIColor.darkGray
btn.addTarget(self, action: #selector(closeAction), for: UIControlEvents.touchUpInside)
return btn
}()
private lazy var SaveBtn:UIButton = {
let btn = UIButton()
btn.setTitle("保存", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.backgroundColor = UIColor.darkGray
btn.addTarget(self, action: #selector(SaveAction), for: UIControlEvents.touchUpInside)
return btn
}()
}
class PicturePrepareLayout:UICollectionViewFlowLayout {
override func prepare() {
itemSize = UIScreen.main.bounds.size
minimumLineSpacing = 0
minimumInteritemSpacing = 0
scrollDirection = UICollectionViewScrollDirection.horizontal
collectionView?.showsHorizontalScrollIndicator = false
collectionView?.isPagingEnabled = true
collectionView?.bounces = false;
}
}
extension PictureVisitControl:UICollectionViewDataSource,PictureVisitControlCellDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pictureUrls?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! PictureVisitControlCell
cell.PictureVisitDelegate = self
cell.imageURL = pictureUrls?[indexPath.row]
return cell
}
func TapPhotoCloseDismiss(cell: PictureVisitControlCell) {
dismiss(animated: true, completion: nil)
}
}
PictureVisitControlCell的实现
import UIKit
import Kingfisher
protocol PictureVisitControlCellDelegate:NSObjectProtocol {
func TapPhotoCloseDismiss(cell:PictureVisitControlCell)
}
class PictureVisitControlCell: UICollectionViewCell {
weak var PictureVisitDelegate : PictureVisitControlCellDelegate?
var imageURL:URL?{
didSet{
reSetPosion()
IMg.kf.setImage(with: imageURL, placeholder:nil, options: nil, progressBlock: nil) { (image, error, _, _) in
//调整图片位置
self.setImgViewPosion()
}
}
}
//调整图片显示的位置
private func setImgViewPosion(){
let size = self.disPlaySize(image: IMg.image!)
if size.height < ScreenHeight{
self.IMg.frame = CGRect.init(origin: CGPoint.zero, size: size)
//处理居中显示
let y = (UIScreen.main.bounds.height - size.height) * 0.5
self.scrollView.contentInset = UIEdgeInsets(top: y, left: 0, bottom: -y, right: 0)
}else
{
self.IMg.frame = CGRect.init(origin: CGPoint.zero, size: size)
scrollView.contentSize = size
}
}
//重置scrollerView和imageView的属性
private func reSetPosion(){
scrollView.contentInset = UIEdgeInsets.zero
scrollView.contentOffset = CGPoint.zero
scrollView.contentSize = CGSize.zero
//重置imageview的属性
IMg.transform = CGAffineTransform.identity
}
private func disPlaySize(image:UIImage)->CGSize{
let scale = image.size.height / image.size.width
let width = UIScreen.main.bounds.width
let height = width * scale
return CGSize(width: width, height: height)
}
override init(frame: CGRect) {
super.init(frame: frame)
SetUpUI()
}
private func SetUpUI(){
contentView.addSubview(scrollView)
scrollView.addSubview(IMg)
//添加布局
scrollView.frame = UIScreen.main.bounds
scrollView.delegate = self
scrollView.maximumZoomScale = 2.0
scrollView.minimumZoomScale = 0.5
IMg.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(close))
IMg.addGestureRecognizer(tap)
}
/// 点击图片关闭控制器
@objc private func close(){
PictureVisitDelegate?.TapPhotoCloseDismiss(cell: self)
}
private lazy var scrollView:UIScrollView = UIScrollView()
lazy var IMg:UIImageView = UIImageView()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension PictureVisitControlCell:UIScrollViewDelegate{
//告诉系统需要缩放的view
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return IMg;
}
//重新调整配图的位置
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
var offSetX = (UIScreen.main.bounds.width - (view?.frame.width)!) * 0.5
var offSetY = (UIScreen.main.bounds.height - (view?.frame.height)!) * 0.5
offSetX = offSetX < 0 ? 0: offSetX
offSetY = offSetY < 0 ? 0: offSetY
scrollView.contentInset = UIEdgeInsets(top: offSetY, left: offSetX, bottom: offSetY, right: offSetX)
}
}
代码文件下载地址