前言:
过去有个项目有了这个需求.当时选择从git上找了个框架直接来用,但是其中很多功能是我并不需要的,以及想要了解一下这一块的具体实现方式,就选择自己参考其重写了一下,主要运用的知识就是photos框架以及图片编辑那一块对view的操作逻辑.
如果对这些感兴趣的可以仔细看下项目参考下.如果只是有类似需求可以直接拉到最下方使用方式.
实现功能:
自定制相册.
实现相片展示页首个cell是拍照功能.
实现相片选中裁切功能.
实现思路:
-
使用photos框架获取手机内所有图片.
-
使用CollectionView将图片展示,并实现首个cell是相机按钮功能.
-
新建控制器实现选中照片编辑功能.
-
使用代理将编辑完照片回调.
实现方式:
-
在info.plist文件中添加相机与相册调用权限.
-
创建EWPickerManager类,用于获取以及存储数据.
-
获取手机内所有相片,PHFetchResult()格式
-
将相片转换成image格式,并将其存储为一个Array.
-
创建相册展示页ViewController.为其添加CollectionView.并将获取的相片数据展示,同时实现首个cell是相机展示.
-
创建相片选中编辑页.为其添加背景展示图片View,上层覆盖半透明View,下方取消确认按钮View.以及中间透明裁切区域View.
-
添加相片方向校正方法,保证相片正常展示.
-
为编辑页添加缩放手势以及拖拽手势.
-
添加frame验证方法,保证相片在缩放拖拽后展示效果.
-
添加相片裁切方法.
-
创建EWImageCropperDelegate将编辑完成的相片回调.
-
添加调用相机功能.
-
为相册展示页CollectionView.Cell添加点击方法.
-
使用自定制navigationController将交互串联.
0.在info.plist文件中添加相机与相册调用权限.
所有与相机相册相关的功能都需要添加权限说明,重要!
<key>NSPhotoLibraryUsageDescription</key>
<string>相册权限</string>
<key>NSCameraUsageDescription</key>
<string>相机权限</string>
1.创建EWPickerManager类,用于获取以及存储数据.
class EWPickerManager: NSObject {
private(set) var photoAlbum = PHFetchResult<PHAsset>()
private var photoManage = PHCachingImageManager()
/// 照片获取偏好设置
private let photoOption = PHImageRequestOptions()
//pickerCell照片的size
class public var pickerPhotoSize: CGSize {
let sreenBounds = ScreenInfo.Frame
let screenWidth = sreenBounds.width > sreenBounds.height ? sreenBounds.height : sreenBounds.width
let width = (screenWidth - CGFloat(9)) / CGFloat(4)
return CGSize(width: width, height: width)
}
override init() {
super.init()
// 如何调整所请求的图像大小。
self.photoOption.resizeMode = .fast //最快速的调整图像大小,有可能比给定大小略大
// 请求的图像质量和交付优先级。
self.photoOption.deliveryMode = .opportunistic //平衡图像质量和响应速度
// 是否同步处理一个图像请求.
self.photoOption.isSynchronous = true
getPhotoAlbums()
}
}
2.获取手机内所有相片,PHFetchResult()格式
/// 获取手机中所有相册照片源
private func getPhotoAlbums(){
//创建一个PHFetchOptions对象检索照片
let options = PHFetchOptions()
//通过创建时间来检索
options.sortDescriptors = [NSSortDescriptor.init(key: "creationDate", ascending: false)]
//通过数据类型来检索,这里为只检索照片
options.predicate = NSPredicate.init(format: "mediaType in %@", [PHAssetMediaType.image.rawValue])
//通过检索条件检索出符合检索条件的所有数据,也就是所有的照片
let allResult = PHAsset.fetchAssets(with: options)
//将获取的相片加入到相片的数组中
photoAlbum = allResult
}
3.将相片转换成image格式,并将其存储为一个Array.
/// 获取手机相册内所有照片
///
/// - Returns: 手机相册内所有照片
public func getAllPhoto() -> [UIImage]{
var imageArray = [UIImage]()
let scale = UIScreen.main.scale
/// 重要,不对size进行重置会使显示效果变差
let photoScaleSize = CGSize(width: EWPickerManager.pickerPhotoSize.width * scale, height: EWPickerManager.pickerPhotoSize.height * scale)
/// 将图片添加到数组
for i in 0 ..< self.photoAlbum.count {
/// 按顺序获取图片
self.photoManage.requestImage(for: self.photoAlbum[i], targetSize: photoScaleSize, contentMode: .aspectFill, options: self.photoOption) { (image, infoDic) in
if image != nil{
imageArray.append(image!)
}
}
}
return imageArray
}
4.创建相册展示页ViewController.为其添加CollectionView.并将获取的相片数据展示,同时实现首个cell是相机展示.
import UIKit
class EWPhotoCollectionViewController: UIViewController {
public var delegate: EWImageCropperDelegate?
private let manager = EWPickerManager()
private var photoArray = [UIImage]()
private let collectionView: UICollectionView = {
let defaultLayout = UICollectionViewFlowLayout()
defaultLayout.scrollDirection = UICollectionViewScrollDirection.vertical//设置垂直显示
defaultLayout.minimumLineSpacing = 3 //每个相邻的layout的上下间隔
defaultLayout.minimumInteritemSpacing = 3.0 //每个相邻layout的左右间隔
let collectionView = UICollectionView(frame:CGRect(x: 0, y: 88, width: ScreenInfo.Width, height: ScreenInfo.Height - ScreenInfo.navigationHeight), collectionViewLayout: defaultLayout)
collectionView.backgroundColor = UIColor.white
return collectionView
}()
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "相册"
getPhotoData()
drawMyView()
drawMyNavigationBar()
}
private func drawMyView(){
self.view.backgroundColor = UIColor.white
collectionView.delegate = self
collectionView.dataSource = self
collectionView.alwaysBounceVertical = true
/// 使用动态注册阻止col