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

边栏推荐
- Techniques d'utilisation de sublime
- [QT] custom control loading
- Complete code of C language neural network and its meaning
- JHOK-ZBL1漏电继电器
- QT控件样式系列(一)之QSlider
- Harmonyos fourth training
- No experts! Growth secrets for junior and intermediate programmers and "quasi programmers" who are still practicing in Universities
- sublime使用技巧
- U++4 interface learning notes
- NiO related knowledge points (I)
猜你喜欢

SQL injection HTTP header injection

SQL injection - secondary injection and multi statement injection

Mysql database (basic)

AttributeError: module ‘torch._ C‘ has no attribute ‘_ cuda_ setDevice‘

What changes will PMP certification bring?

ThinkPHP Association preload with

Sublime tips

人体传感器好不好用?怎么用?Aqara绿米、小米之间到底买哪个

Pytest testing framework -- data driven

qt 简单布局 盒子模型 加弹簧
随机推荐
Knapsack problem (01 knapsack, complete knapsack, dynamic programming)
Full link voltage test: the dispute between shadow database and shadow table
If you‘re running pod install manually, make sure flutter pub get is executed first.
Longest palindrome substring (dynamic programming)
Techniques d'utilisation de sublime
Dynamically generate tables
【opencv】图像形态学操作-opencv标记不同连通域的位置
Y58. Chapter III kubernetes from entry to proficiency - continuous integration and deployment (Sany)
sublime使用技巧
The sooner you understand the four rules of life, the more blessed you will be
As we media, what websites are there to download video clips for free?
漏电继电器JD1-100
qt 简单布局 盒子模型 加弹簧
【问道】编译原理
Safe landing practice of software supply chain under salesforce containerized ISV scenario
2. Overview of securities investment funds
[question] Compilation Principle
2039: [蓝桥杯2022初赛] 李白打酒加强版 (动态规划)
高数中值定理总结
Complete code of C language neural network and its meaning