当前位置:网站首页>照片选择器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.效果图

边栏推荐
- Full link voltage test: the dispute between shadow database and shadow table
- 数字化如何影响工作流程自动化
- The sooner you understand the four rules of life, the more blessed you will be
- npm ERR! 400 Bad Request - PUT xxx - “devDependencies“ dep “xx“ is not a valid dependency name
- U++ game learning notes
- DJ-ZBS2漏电继电器
- ClickHouse(03)ClickHouse怎么安装和部署
- If you‘re running pod install manually, make sure flutter pub get is executed first.
- 局部变量的数组初始化问题
- DFS,BFS以及图的遍历搜索
猜你喜欢

torch optimizer小解析

K6EL-100漏电继电器

DJ-ZBS2漏电继电器

U++ metadata specifier learning notes

Safe landing practice of software supply chain under salesforce containerized ISV scenario

Leetcode (46) - Full Permutation

使用知云阅读器翻译统计遗传学书籍

PMP证书有没有必要续期?

Error: No named parameter with the name ‘foregroundColor‘

Auto.js 获取手机所有app名字
随机推荐
局部变量的数组初始化问题
漏电继电器JOLX-GS62零序孔径Φ100
Wonderful express | Tencent cloud database June issue
Operand of null-aware operation ‘!‘ has type ‘SchedulerBinding‘ which excludes null.
【问道】编译原理
Longest common subsequence (LCS) (dynamic programming, recursive)
利用OPNET进行网络任意源组播(ASM)仿真的设计、配置及注意点
Simulate thread communication
高数中值定理总结
全链路压测:影子库与影子表之争
Safe landing practice of software supply chain under salesforce containerized ISV scenario
Dynamically generate tables
K6EL-100漏电继电器
漏电继电器LLJ-100FS
最长公共子序列(LCS)(动态规划,递归)
Dbsync adds support for mongodb and ES
精彩速递|腾讯云数据库6月刊
Leetcode longest public prefix
【PHP SPL笔记】
在米家、欧瑞博、苹果HomeKit趋势下,智汀如何从中脱颖而出?