Swift封装图片浏览,多张图片浏览,缩放,gif图片的播放

封装了一个图片浏览器,实现了图片的浏览,缩放,支持多张图片的浏览缩放,保存到相册等功能

实现功能

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)


    }

}

代码文件下载地址

你可能感兴趣的:(Swift)