Photos框架 - 自定义媒体选择器(UI列表)

打印 上一主题 下一主题

主题 998|帖子 998|积分 2994

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

弁言
Photos框架 - 自定义媒体资源选择器(数据部门)-CSDN博客


关于自定义媒体选择器上一篇博客我们已经先容了使用Photos获取媒体资源数据和处理媒体资源数据,有了数据,UI的实现就比力灵活了,我就以上面的设计样式为例,然后把重点放到底部图片和视频的选择地区上。
创建媒体选择器

本篇博客我们就来讨论一下媒体资源选择器UI部门的实现,先来实现一下简单的选中和取消选中以及获取选中结果的功能。
选择器UI实现

由于UI的功能都很基础我们就将它分成列表和预览两大部门来处理。
列表部门

1.创建视图控制器

首先继承自UIViewController创建了一个名为PHMediaPickerViewController的类当做列表的视图控制器,为视图控制器定义列表,媒体资源管理类,已经选中的资源列表等信息,代码如下:
  1. class PHMediaPickerViewController: UIViewController {
  2.    
  3.     /// 列表
  4.     private var collectionView: UICollectionView!
  5.     /// 媒体资源管理类
  6.     private var mediaManager:PHMediaManager!
  7.    
  8.     /// 数据源
  9.     private var dataSource: [Any] = []
  10.     /// 选中的资源
  11.     private var selectedMediaModels: [PHMediaModel] = []
  12.     /// 最大选中数量
  13.     private var maxSelectedCount: Int = 9
  14.     override func viewDidLoad() {
  15.         super.viewDidLoad()
  16.         initData()
  17.         addCollectionView()
  18.         requestPhotoLibraryAuthorization()
  19.     }
  20.     ....
  21. }
复制代码
2.初始化数据

根据默认的设置信息来初始化媒体资源管理器,以及数据源列表,并为列表添加两个字符串类型的元素,当做是调取摄像头拍摄图片和视频的item。
  1.     func initData() {
  2.         let config = PHMediaConfig()
  3.         mediaManager = PHMediaManager(config: config)
  4.         let actionArray = ["photo","video"]
  5.         dataSource.append(contentsOf: actionArray)
  6.     }
复制代码
3.创建列表

初始化列表,我们设置为4列的列表,列间间距和行间距都为2.0。并注册展示媒体资源类型的cell和展示操纵相机类型的cell,代码如下:
  1.     /// 添加列表
  2.     func addCollectionView()  {
  3.         let layout = UICollectionViewFlowLayout()
  4.         let itemWidth = (CS_SCREENWIDTH - (2.0 * 3)) / 4.0
  5.         layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
  6.         layout.minimumLineSpacing = 2.0
  7.         layout.minimumInteritemSpacing = 0.0
  8.         collectionView = UICollectionView(frame: CGRect(x: 0, y: cs_navigationBarHeight, width: CS_SCREENWIDTH, height: CS_SCREENHIGHT - cs_navigationBarHeight), collectionViewLayout: layout)
  9.         collectionView.contentInset = UIEdgeInsets(top: 0.0, left: 0.0, bottom: cs_bottomInset, right: 0.0)
  10.         collectionView.delegate = self
  11.         collectionView.dataSource = self
  12.         self.view.addSubview(collectionView)
  13.         // 注册 媒体资源类型cell
  14.         collectionView.register(PHMediaPickerCell.self, forCellWithReuseIdentifier: NSStringFromClass(PHMediaPickerCell.self))
  15.         // 注册 操作cell
  16.         collectionView.register(PHMediaPickerOperateCell.self, forCellWithReuseIdentifier: NSStringFromClass(PHMediaPickerOperateCell.self))
  17.     }
复制代码
4.哀求媒体资源数据

在哀求媒体资源前记得先检查权限,获取到权限之后开始哀求媒体数据并添加到列表中回到主线程刷线,代码如下:
  1.     func requestPhotoLibraryAuthorization() {
  2.         mediaManager.requestPhotoLibraryAuthorization {[weak self] (isAuthorized) in
  3.             guard let self = self else { return }
  4.             if isAuthorized {
  5.                 self.requstMediaData()
  6.             } else {
  7.                 print("没有权限")
  8.             }
  9.         }
  10.     }
  11.    
  12.     func requstMediaData() {
  13.         mediaManager.fetchLocalAlbums {[weak self] (mediaModels) in
  14.             guard let self = self else { return }
  15.             self.dataSource.append(contentsOf: mediaModels)
  16.             DispatchQueue.main.async {
  17.                 self.collectionView.reloadData()
  18.             }
  19.         }
  20.     }
复制代码
5.根据数据渲染列表

实现代理方法,根据数据类型来渲染列表的数据,代码如下:
  1.     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  2.         return dataSource.count
  3.     }
  4.    
  5.     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  6.         let item = dataSource[indexPath.row]
  7.         if let mediaModel = item as? PHMediaModel {
  8.             let cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(PHMediaPickerCell.self), for: indexPath) as! PHMediaPickerCell
  9.             let index = selectedMediaModels.firstIndex(of: mediaModel) ?? -1
  10.             if index == -1 {
  11.                 cell.setNormal()
  12.             } else {
  13.                 cell.setSelected(index: index)
  14.             }
  15.             cell.renderData(mediaModel: mediaModel, mediaManager: mediaManager)
  16.             return cell
  17.         } else {
  18.             let cell = collectionView.dequeueReusableCell(withReuseIdentifier: NSStringFromClass(PHMediaPickerOperateCell.self), for: indexPath) as! PHMediaPickerOperateCell
  19.             
  20.             return cell
  21.         }
  22.     }
复制代码
PHMediaPickerOperateCell类型的Item就只使用制定图片渲染即可,而PHMediaPickerCell的item相对而言元素必要多一些,选中状态以及视频的时长等等,代码如下:
  1. class PHMediaPickerCell: UICollectionViewCell {
  2.    
  3.     /// 图片
  4.     private var imageView = UIImageView()
  5.     /// 选中标签
  6.     private var selectTag = UILabel()
  7.     /// 播放按钮
  8.     private var playButton = UIButton()
  9.     /// 资源模型
  10.     private var mediaModel: PHMediaModel?
  11.     /// 资源管管理类
  12.     private var mediaManager: PHMediaManager?
  13.     .....
  14.     .....
  15.     /// 渲染数据
  16.     func renderData(mediaModel: PHMediaModel, mediaManager: PHMediaManager) {
  17.         self.mediaModel = mediaModel
  18.         self.mediaManager = mediaManager
  19.         playButton.isHidden = mediaModel.mediaType != .video
  20.         let duration = Int(mediaModel.videoDuration)
  21.         let title = secondsToHourMinuteSecond(seconds: duration)
  22.         playButton.setTitle(title, for: .normal)
  23.         self.mediaManager?.fetchThumbnail(asset: mediaModel.asset!, completion: {[weak self] (image) in
  24.             guard let self = self else { return }
  25.             self.imageView.image = image
  26.         })
  27.     }
  28. }
复制代码
我们省略了一些关于创建UI和结构代码,把重点放到数据的渲染上,这里直接使用mediaManager读取缩略图数据,而mediaManager是直接从视图控制器传递过来的,所以每个item都将共享缩略图的缓存。
6.资源的选中和取消

下面就是资源的选择和取消选择功能了,我们设置了资源最大选中数量为9个,那么就必要在选中时举行判定,详细代码如下:
  1.     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  2.         let item = dataSource[indexPath.row]
  3.         if let mediaModel = item as? PHMediaModel {
  4.             // 点击媒体资源
  5.             self.collectionView(collectionView, didSelectItemAt: indexPath, mediaModel: mediaModel)
  6.         } else {
  7.             // 点击操作
  8.             self.collectionView(collectionView, didSelectItemAt: indexPath, action: item as! String)
  9.         }
  10.         
  11.     }
  12.    
  13.     /// 媒体点击
  14.     private func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath,mediaModel:PHMediaModel) {
  15.         if mediaModel.isSelected {
  16.             mediaModel.isSelected = false
  17.             if let index = selectedMediaModels.firstIndex(of: mediaModel) {
  18.                 selectedMediaModels.remove(at: index)
  19.             }
  20.         } else {
  21.             if selectedMediaModels.count >= maxSelectedCount {
  22.                 print("最多选中\(maxSelectedCount)个")
  23.                 return
  24.             }
  25.             mediaModel.isSelected = true
  26.             selectedMediaModels.append(mediaModel)
  27.         }
  28.         collectionView.reloadData()
  29.     }
复制代码
接下来我们只必要读取selectedMediaModels的内容就可以获取到我们选中的媒体资源列表了。
但是会有另外一个题目,就是目前通过数组里面的元素我们只能获取到缩略图,还没有获取到原图和原视频资源。
这时间仍然有两个方案,我们可以在点击的时间就开始加载媒体的原始资源,或者我们可以在必要的时间才开始加载原始资源,两个方案都是可以的,我们在下一篇博客再来讨论它们。
结语

本篇博客我们使用已经获取到的媒体数据创建了一个基础的媒体资源选择列表页面。并且使用实现了列表资源的选择和取消选择功能。
至此整个资源选择列表的功能算是完成了,但是常见的资源列表往往还会有一个资源大图的预览功能,下一篇博客我们就来讨论一下媒体原始资源的加载机遇,并实现预览功能。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表