当前位置:网站首页>照片选择器CollectionView
照片选择器CollectionView
2022-07-06 23:27:00 【Hanyang Li】
1. 定义PicturePickerController
import UIKit
//可重用 Cell
private let PicturePickerCellId = "PicturePickerCellId"
//最大选择照片数量
private let PicturePickerMaxCount = 8
//MARK: - 照片选择器
class PicturePickerController: UICollectionViewController {
//配图数组
lazy var pictures = [UIImage]()
//当前用户选中的照片索引
private var selectedIndex = 0
//MARK: - 构造函数
init(){
super.init(collectionViewLayout: PicturePickerLayout())
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// 在 collectionViewController 中 collectionView != view
override func viewDidLoad() {
super.viewDidLoad()
//self.collectionView.backgroundColor = .orange
self.collectionView!.register(PicturePickerCell.self, forCellWithReuseIdentifier: PicturePickerCellId)
}
//照片选择器布局
private class PicturePickerLayout: UICollectionViewFlowLayout{
override func prepare() {
// iOS 9.0 之后 ,iPad 支持分屏,不建议过分依赖 UIScreen 作为布局参照
super.prepare()
let count = 4.0
let margin = UIScreen.main.scale * 4
let w = (collectionView!.bounds.width - (count + 1) * margin) / count
itemSize = CGSize(width: w, height: w)
sectionInset = UIEdgeInsets(top: margin, left: margin, bottom: 0, right: margin)
minimumLineSpacing = margin
minimumInteritemSpacing = margin
}
}
}
2.扩展分类,数据源实现
extension PicturePickerController{
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//保证末尾有一个加号按钮 如果达到上限,不显示 + 按钮 pictures.count + (pictures.count == PicturePickerMaxCount ? 0 : 1)
return pictures.count + 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PicturePickerCellId, for: indexPath) as! PicturePickerCell
cell.pictureDelegate = self
cell.image = indexPath.item < pictures.count ? pictures[indexPath.item] : nil
cell.hiddenButton = (indexPath.item == PicturePickerMaxCount)
return cell
}
}
3.实现Cell 中代理方法
//MARK: - PicturePickerCellDelegate
extension PicturePickerController: PicturePickerCellDelegate{
func picturePickerCellDidAdd(cell: PicturePickerCell) {
//判断是否允许访问相册
/**
PhotoLibrary 保存的照片 + 同步的照片
SavedPhotosAlbum 保存的照片/屏幕的截图/拍照
*/
if !UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum){
print("无法访问照片库")
return
}
//记录当前用户选中的照片索引
selectedIndex = collectionView!.indexPath(for: cell)?.item ?? 0
let picker = UIImagePickerController()
picker.modalPresentationStyle = .fullScreen
picker.delegate = self
//picker.allowsEditing = true
present(picker, animated: true)
}
func picturePickerCellDidRemove(cell: PicturePickerCell) {
//1.获取照片索引
let indexPath = collectionView.indexPath(for: cell)!
//2.判断索引是否超出上限
if indexPath.item >= pictures.count{
return
}
collectionView.performBatchUpdates {
//3.删除数据
pictures.remove(at: indexPath.item)
//4.动画刷新数据
collectionView.deleteItems(at: [indexPath])
} completion: { finished in
//5.刷新数据
self.collectionView.reloadData()
}
}
}
4.UIImagePickerController 遵守的协议
//MARK: - UIImagePickerController 遵守的协议
extension PicturePickerController: UIImagePickerControllerDelegate, UINavigationControllerDelegate{
/// 照片选择完成
/// - Parameters:
/// - picker: 照片选择控制器
/// - info: info 字典
/// - 提示: 一旦实现代理方法,必须自己 dismiss
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
/**
如果使用 cocos2dx 开发一个 ‘空白的模板’游戏,内存占用 70M iOS UI 的空白应用程序,大概 19M
一般应用程序,内存在 100M 左右都是能够接受的,再高就需要注意
*/
let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let scaleImage = image.scaleToWith(width: 600)
//将图像添加到数组
//判断当前选中的索引是否超出数组
if selectedIndex >= pictures.count{
pictures.append(scaleImage)
}else{
pictures[selectedIndex] = scaleImage
}
//释放控制器
dismiss(animated: true) {
//刷新视图
self.collectionView.reloadData()
}
}
}
5.PicturePickerCellDelegate 代理
///PicturePickerCellDelegate 代理
///如果协议中包含 optional 的函数,协议需要使用 @objc 修饰
@objc
protocol PicturePickerCellDelegate: NSObjectProtocol{
/// 添加照片
@objc optional func picturePickerCellDidAdd(cell: PicturePickerCell)
/// 移除照片
@objc optional func picturePickerCellDidRemove(cell: PicturePickerCell)
}
6.照片选择 Cell
//照片选择 Cell
class PicturePickerCell: UICollectionViewCell{
//照片选择代理
weak var pictureDelegate: PicturePickerCellDelegate?
var image: UIImage? {
didSet{
addButton.setImage(image ?? UIImage(named: "compose_pic_add"), for: .normal)
//隐藏删除按钮 image == nil 就是新增按钮
removeButton.isHidden = (image == nil)
}
}
var hiddenButton: Bool? {
didSet{
addButton.isHidden = hiddenButton ?? false
}
}
//MARK: - 监听方法
///添加照片
@objc func addPicture(){
pictureDelegate?.picturePickerCellDidAdd?(cell: self)
}
///移除照片
@objc func removePicture(){
pictureDelegate?.picturePickerCellDidRemove?(cell: self)
}
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//设置控件
private func setupUI(){
//1.添加控件
contentView.addSubview(addButton)
contentView.addSubview(removeButton)
//2.设置布局
addButton.frame = bounds
removeButton.snp.makeConstraints { make in
make.top.equalTo(contentView.snp.top)
make.right.equalTo(contentView.snp.right)
}
//3.监听方法
addButton .addTarget(self, action: #selector(addPicture), for: .touchUpInside)
removeButton.addTarget(self, action: #selector(removePicture), for: .touchUpInside)
//4.设置填充模式
addButton.imageView?.contentMode = .scaleAspectFill
}
//MARK: - 懒加载控件
///添加按钮
private lazy var addButton = UIButton(imageName: "compose_pic_add", backImageName: nil)
///删除按钮
private lazy var removeButton = UIButton(imageName: "compose_photo_close", backImageName: nil)
}
7.效果图
边栏推荐
猜你喜欢
随机推荐
Knapsack problem unrelated to profit (depth first search)
DJ-ZBS2漏电继电器
How does redis implement multiple zones?
If you‘re running pod install manually, make sure flutter pub get is executed first.
Scheduledexecutorservice timer
The execution order of return in JS' try catch finally
SQL injection cookie injection
DFS,BFS以及图的遍历搜索
实现网页内容可编辑
NPDP产品经理认证,到底是何方神圣?
SQL injection HTTP header injection
Wonderful express | Tencent cloud database June issue
在米家、欧瑞博、苹果HomeKit趋势下,智汀如何从中脱颖而出?
Techniques d'utilisation de sublime
批量归一化(标准化)处理
When knative meets webassembly
What changes will PMP certification bring?
Let f (x) = Σ x^n/n^2, prove that f (x) + F (1-x) + lnxln (1-x) = Σ 1/n^2
Auto.js 获取手机所有app名字
高手勿进!写给初中级程序员以及还在大学修炼的“准程序员”的成长秘籍