KSMediaPickerController.swift 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. //
  2. // KSMediaPickerController.swift
  3. //
  4. //
  5. // Created by kinsun on 2019/3/1.
  6. //
  7. import UIKit
  8. open class KSNavigationController: UINavigationController {
  9. override open func viewDidLoad() {
  10. super.viewDidLoad()
  11. view.sendSubviewToBack(navigationBar)
  12. }
  13. }
  14. import Photos
  15. import JXSegmentedView
  16. @objc public protocol KSMediaPickerControllerDelegate: NSObjectProtocol {
  17. @objc optional func mediaPicker(_ mediaPicker: KSMediaPickerController, didFinishSelected outputArray: [KSMediaPickerOutputModel])
  18. }
  19. open class KSMediaPickerController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
  20. deinit {
  21. NXLLog("deinit")
  22. }
  23. typealias DismissClosure = () -> Void
  24. var dismissClosure: DismissClosure?
  25. typealias CropClosure = (_ vItemMdl: KSMediaPickerItemModel) -> Void
  26. var cropClosure: CropClosure?
  27. typealias PubImgClosure = (_ selectedAssetArray: Array<UIImage>) -> Void
  28. var pubImgClosure: PubImgClosure?
  29. typealias PubEditImgClosure = (_ selectedAssetArray: Array<UIImage>) -> Void
  30. var pubEditImgClosure: PubEditImgClosure?
  31. @objc public enum mediaType : Int {
  32. case all = 0
  33. case picture = 1
  34. case video = 2
  35. }
  36. @objc enum jumpType : Int {
  37. case publish = 0
  38. case publishEdit = 1
  39. }
  40. @objc public let maxItemCount: UInt
  41. @objc public let maxVideoItemCount: UInt
  42. @objc public let maxPictureItemCount: UInt
  43. @objc public var mediaType: KSMediaPickerController.mediaType
  44. var jumpType: KSMediaPickerController.jumpType?
  45. @objc open weak var delegate: KSMediaPickerControllerDelegate?
  46. var curSelectCount: UInt = 0
  47. /// 限制单一媒体类型混合显示构造函数,此函数为指定初始化器
  48. ///
  49. /// - Parameters:
  50. /// - maxVideoItemCount: 选择视频的最大数量
  51. /// - maxPictureItemCount: 选择图片的最大数量
  52. @objc public init(maxVideoItemCount: UInt, maxPictureItemCount: UInt) {
  53. if maxVideoItemCount == 0 {
  54. self.mediaType = .picture
  55. } else if maxPictureItemCount == 0 {
  56. self.mediaType = .video
  57. } else {
  58. self.mediaType = .all
  59. }
  60. maxItemCount = maxVideoItemCount+maxPictureItemCount
  61. self.maxPictureItemCount = maxPictureItemCount
  62. self.maxVideoItemCount = maxVideoItemCount
  63. super.init(nibName: nil, bundle: nil)
  64. }
  65. /// 自由视频与图片构造函数,就是图片加视频的总数为maxItemCount,不对每种做限制只对总数做限制,此函数为指定初始化器
  66. ///
  67. /// - Parameter maxItemCount: 选择媒体的最大总数
  68. @objc public init(maxItemCount: UInt = 9) {
  69. self.mediaType = .all
  70. self.maxItemCount = maxItemCount
  71. maxPictureItemCount = 0
  72. maxVideoItemCount = 0
  73. super.init(nibName: nil, bundle: nil)
  74. }
  75. @nonobjc required public init?(coder aDecoder: NSCoder) {
  76. fatalError("init(coder:) has not been implemented")
  77. }
  78. private static let k_image_item_class = KSMediaPickerViewImageCell.self
  79. private static let k_video_item_class = KSMediaPickerViewVideoCell.self
  80. private static let k_image_item_iden = NSStringFromClass(k_image_item_class)
  81. private static let k_video_item_iden = NSStringFromClass(k_video_item_class)
  82. var tableView : UITableView?
  83. override open func loadView() {
  84. let view = KSMediaPickerView()
  85. view.jumpType = self.jumpType
  86. let nav = view.albumNavigationView
  87. nav.closeButton.addTarget(self, action: #selector(_didClick(closeButton:)), for: .touchUpInside)
  88. nav.nextButton.addTarget(self, action: #selector(_didClick(nextButton:)), for: .touchUpInside)
  89. nav.centerButton.addTarget(self, action: #selector(_chengedAlbumListStatus(_:)), for: .touchUpInside)
  90. let classObj = KSMediaPickerController.self
  91. let collectionView = view.collectionView
  92. collectionView.register(classObj.k_image_item_class, forCellWithReuseIdentifier: classObj.k_image_item_iden)
  93. collectionView.register(classObj.k_video_item_class, forCellWithReuseIdentifier: classObj.k_video_item_iden)
  94. collectionView.delegate = self
  95. collectionView.dataSource = self
  96. tableView = view.albumTableView
  97. tableView?.delegate = self
  98. tableView?.dataSource = self
  99. self.view = view
  100. }
  101. override open func viewDidDisappear(_ animated: Bool) {
  102. super.viewDidDisappear(animated)
  103. (view as! KSMediaPickerView).previewView.videoPause()
  104. }
  105. override open func viewDidAppear(_ animated: Bool) {
  106. super.viewDidAppear(animated)
  107. (view as! KSMediaPickerView).previewView.videoPlay()
  108. }
  109. override open func viewDidLoad() {
  110. super.viewDidLoad()
  111. let cancelHandler: ((UIAlertAction) -> Void) = {[weak self] (action) in
  112. self?._didClick(closeButton: nil)
  113. }
  114. KSMediaPickerController.authorityCheckUp(controller: self, type: .picture, completionHandler: {[weak self] (type) in
  115. if let obj = self {
  116. KSMediaPickerController.authorityCheckUp(controller: obj, type: .video, completionHandler: { (type) in
  117. KSMediaPickerController.authorityAudioCheckUp(controller: obj, completionHandler: {
  118. DispatchQueue.global().async {
  119. let assetCollections = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: nil)
  120. let regularAssetCollections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: nil)
  121. let array = [assetCollections, regularAssetCollections]
  122. self?._set(assetData: array)
  123. }
  124. }, cancelHandler: cancelHandler)
  125. }, cancelHandler: cancelHandler)
  126. }
  127. }, cancelHandler: cancelHandler)
  128. }
  129. private var _albumList: [KSMediaPickerAlbumModel]?
  130. private func _set(assetData: [PHFetchResult<PHAssetCollection>]) {
  131. _albumList = KSMediaPickerAlbumModel.albumModel(from: assetData, mediaType: self.mediaType)
  132. DispatchQueue.main.async(execute: _loadAssetDataFinish)
  133. }
  134. private var _selectedAlbum: KSMediaPickerAlbumModel? {
  135. didSet {
  136. let view = self.view as! KSMediaPickerView
  137. _updateHighlightedItemStatus()
  138. if let itemModel = _selectedAlbum?.assetList.first {
  139. let isStandard = _selectedAssetArray.count == 0 || itemModel == (_selectedAssetArray.firstObject as! KSMediaPickerItemModel)
  140. view.previewView.set(itemModel: itemModel, isStandard: isStandard)
  141. itemModel.isHighlight = true
  142. }
  143. _highlightedItemIndexPath = IndexPath(item: 0, section: 0)
  144. view.albumNavigationView.centerButton.setTitle(_selectedAlbum?.albumTitle, for: UIControl.State.normal)
  145. view.albumNavigationView.centerButton.layoutButton(edgeInsetsStyle: ButtonEdgeInsetsStyle.right, imageTitleSpace: 1)
  146. view.collectionView.reloadData()
  147. }
  148. }
  149. private func _loadAssetDataFinish() {
  150. (view as! KSMediaPickerView).albumTableView.reloadData()
  151. _selectedAlbum = _albumList?.first
  152. }
  153. typealias IsHiddenSegmentedViewClosure = (Bool) -> Void
  154. var isHiddenSegmentedViewClosure : IsHiddenSegmentedViewClosure?
  155. @objc private func _chengedAlbumListStatus(_ button: UIButton) {
  156. let isShow = (view as! KSMediaPickerView).chengedAlbumListStatus()
  157. if let isHiddenSegmentedViewClosure = isHiddenSegmentedViewClosure {
  158. isHiddenSegmentedViewClosure(isShow)
  159. }
  160. if isShow {
  161. button.setImage(kImage(name: "ico_arrow_down"), for: UIControl.State.normal)
  162. }else {
  163. button.setImage(kImage(name: "ico_arrow_up"), for: UIControl.State.normal)
  164. }
  165. button.setTitle(self._selectedAlbum?.albumTitle, for: UIControl.State.normal)
  166. button.layoutButton(edgeInsetsStyle: ButtonEdgeInsetsStyle.right, imageTitleSpace: 1)
  167. }
  168. @objc private func _didClick(closeButton: UIButton?) {
  169. if self.jumpType == .publishEdit {
  170. self.dismiss(animated: true, completion: nil)
  171. }else {
  172. if let dismissClosure = self.dismissClosure {
  173. (view as! KSMediaPickerView).previewView.videoPause()
  174. dismissClosure()
  175. }
  176. }
  177. }
  178. @objc private func _didClick(nextButton: UIButton) {
  179. (view as! KSMediaPickerView).previewView.saveCurrentState()
  180. if _currentSingleType == .video {
  181. if let cropClosure = self.cropClosure {
  182. (view as! KSMediaPickerView).previewView.videoPause()
  183. let vItemModel: KSMediaPickerItemModel = _selectedAssetArray.firstObject as! KSMediaPickerItemModel
  184. cropClosure(vItemModel)
  185. }
  186. } else {
  187. var imageArray: Array<UIImage> = []
  188. for (index, selItem) in _selectedAssetArray.enumerated() {
  189. let itemModel = selItem as! KSMediaPickerItemModel
  190. // 添加选中image
  191. let asset = itemModel.asset
  192. var pixelWidth = CGFloat(asset.pixelWidth)
  193. var pixelHeight = CGFloat(asset.pixelHeight)
  194. if pixelWidth > 1080 {
  195. pixelWidth = 1080
  196. pixelHeight = 1080 * pixelHeight / pixelWidth
  197. }
  198. PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width: pixelWidth, height: pixelHeight), contentMode: .aspectFit, options: KSMediaPickerItemModel.pictureOptions) { (image, info) in
  199. image?.pngData()
  200. let image1 = UIImage(data: (image?.pngData())!, scale: 0.6)
  201. imageArray.append(image1!)
  202. }
  203. if index == self._selectedAssetArray.count-1 {
  204. if self.jumpType == .publishEdit {
  205. if let pubEditImgClosure = self.pubEditImgClosure {
  206. pubEditImgClosure(imageArray)
  207. }
  208. self.dismiss(animated: true, completion: nil)
  209. }else {
  210. if let pubImgClosure = self.pubImgClosure {
  211. (self.view as! KSMediaPickerView).previewView.videoPause()
  212. pubImgClosure(imageArray)
  213. }
  214. }
  215. }
  216. }
  217. }
  218. }
  219. private func _didClickCell(collectionViewCell: KSMediaPickerViewImageCell) -> UInt {
  220. guard let itemModel = collectionViewCell.itemModel, !itemModel.isLoseFocus else {
  221. return 0
  222. }
  223. let indexPath = (view as! KSMediaPickerView).collectionView.indexPath(for: collectionViewCell)
  224. if indexPath != nil {
  225. _updateHighlightItem(at: indexPath!)
  226. }
  227. var selCount: UInt = 0
  228. var maxCount : UInt?
  229. if itemModel.asset.mediaType == .video {
  230. maxCount = maxVideoItemCount
  231. }else {
  232. maxCount = maxPictureItemCount
  233. }
  234. if itemModel.index > 0 {
  235. selCount = _remove(itemModel: itemModel)
  236. curSelectCount -= 1
  237. } else {
  238. selCount = _add(itemModel: itemModel)
  239. curSelectCount = UInt(_selectedAssetArray.count)
  240. }
  241. (view as! KSMediaPickerView).albumTableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: UITableView.RowAnimation.none)
  242. updateFinishBtnStatus(curSelectCount, maxCount!)
  243. return selCount
  244. }
  245. // 更新
  246. func updateFinishBtnStatus(_ selCount: UInt, _ maxCount: UInt) {
  247. let showMaxCount = selCount == 0 ? 0 : maxCount
  248. let view = self.view as! KSMediaPickerView
  249. let nav = view.albumNavigationView
  250. if selCount == 0 {
  251. nav.nextButton.setTitle("完成", for: .normal)
  252. }else {
  253. nav.nextButton.setTitle("完成(\(selCount)/\(showMaxCount))", for: .normal)
  254. }
  255. }
  256. private func _update(asset: PHAsset) {
  257. _updateHighlightedItemStatus()
  258. let itemModel = KSMediaPickerItemModel(asset)
  259. itemModel.isHighlight = true
  260. _selectedAlbum?.assetList.insert(itemModel, at: 0)
  261. let indexPath = IndexPath(item: 0, section: 0)
  262. _highlightedItemIndexPath = indexPath
  263. let isStandard = _selectedAssetArray.count == 0 || itemModel == (_selectedAssetArray.firstObject as! KSMediaPickerItemModel)
  264. let view = self.view as! KSMediaPickerView
  265. view.previewView.set(itemModel: itemModel, isStandard: isStandard)
  266. let collectionView = view.collectionView
  267. collectionView.performBatchUpdates({
  268. collectionView.insertItems(at: [indexPath])
  269. }) {[weak self] (finished) in
  270. let index = self?._add(itemModel: itemModel) ?? 0
  271. if index > 0 {
  272. itemModel.index = index
  273. } else {
  274. itemModel.isLoseFocus = true
  275. }
  276. collectionView.reloadItems(at: [indexPath])
  277. view.collectionViewScrollToTop()
  278. }
  279. }
  280. private lazy var _selectedAssetArray = NSMutableArray(capacity: Int(maxItemCount))
  281. private func _add(itemModel: KSMediaPickerItemModel) -> UInt {
  282. let selectedAssetArray = _selectedAssetArray
  283. let count = UInt(selectedAssetArray.count)
  284. var k_maxItemCount = maxItemCount
  285. let assetMediaType = (selectedAssetArray.firstObject as? KSMediaPickerItemModel)?.asset.mediaType ?? itemModel.asset.mediaType
  286. var isSingleType = false
  287. if self.mediaType == .all {
  288. if assetMediaType == .video && maxVideoItemCount != 0 {
  289. k_maxItemCount = maxVideoItemCount
  290. _currentSingleType = .video
  291. } else if assetMediaType == .image && maxPictureItemCount != 0 {
  292. k_maxItemCount = maxPictureItemCount
  293. _currentSingleType = .picture
  294. }
  295. if _currentSingleType != nil && count == 0 {
  296. isSingleType = true
  297. }
  298. }
  299. guard count < k_maxItemCount else {
  300. return 0
  301. }
  302. selectedAssetArray.add(itemModel)
  303. let lastCount = count+1
  304. let isLastItem = lastCount == k_maxItemCount
  305. let view = self.view as! KSMediaPickerView
  306. if isSingleType || isLastItem {
  307. let assetList = _selectedAlbum!.assetList
  308. var indexPaths = Array<IndexPath>()
  309. for (i, k_itemModel) in assetList.enumerated() {
  310. let isOk = (isSingleType && k_itemModel.asset.mediaType != assetMediaType) || (isLastItem && !selectedAssetArray.contains(k_itemModel))
  311. if isOk && !k_itemModel.isLoseFocus {
  312. k_itemModel.isLoseFocus = true
  313. let indexPath = IndexPath(item: i, section: 0)
  314. indexPaths.append(indexPath)
  315. }
  316. }
  317. let collectionView = view.collectionView
  318. collectionView.performBatchUpdates({
  319. collectionView.reloadItems(at: indexPaths)
  320. }, completion: nil)
  321. }
  322. view.albumNavigationView.nextButton.isEnabled = lastCount > 0
  323. return lastCount
  324. }
  325. private var _currentSingleType: KSMediaPickerController.mediaType?
  326. private func _remove(itemModel: KSMediaPickerItemModel) -> UInt {
  327. let selectedAssetArray = _selectedAssetArray
  328. let index = selectedAssetArray.index(of: itemModel)
  329. let count = selectedAssetArray.count
  330. guard index >= 0, index < count else {
  331. return 0
  332. }
  333. itemModel.index = 0
  334. selectedAssetArray.removeObject(at: index)
  335. let view = self.view as! KSMediaPickerView
  336. let assetMediaType = itemModel.asset.mediaType
  337. var k_maxItemCount = maxItemCount
  338. var needUpdateSingleType = false
  339. let isSingleType = _currentSingleType != nil
  340. if isSingleType {
  341. if _currentSingleType! == .video {
  342. k_maxItemCount = maxVideoItemCount
  343. } else if _currentSingleType! == .picture {
  344. k_maxItemCount = maxPictureItemCount
  345. }
  346. needUpdateSingleType = count == 1
  347. }
  348. let needUpdateIndexNumber = index != count-1
  349. let needUpdateFocus = count == k_maxItemCount
  350. if needUpdateIndexNumber && needUpdateFocus {
  351. let assetList = _selectedAlbum!.assetList
  352. var j = Int(1)
  353. for k_itemModel in assetList {
  354. if selectedAssetArray.contains(k_itemModel) {
  355. k_itemModel.index = UInt(j)
  356. j += 1
  357. } else {
  358. let ok = isSingleType ? (assetMediaType == k_itemModel.asset.mediaType) : true
  359. if (needUpdateSingleType || (ok && k_itemModel.isLoseFocus)) {
  360. k_itemModel.isLoseFocus = false
  361. }
  362. }
  363. }
  364. let collectionView = view.collectionView
  365. collectionView.reloadData()
  366. } else if needUpdateIndexNumber {
  367. let assetList = _selectedAlbum!.assetList as NSArray
  368. let assetListCount = assetList.count
  369. var indexPaths = Array<IndexPath>()
  370. for (i, k_itemModel) in selectedAssetArray.enumerated() {
  371. let l_itemModel = k_itemModel as! KSMediaPickerItemModel
  372. l_itemModel.index = UInt(i+1)
  373. let k_index = assetList.index(of: l_itemModel)
  374. if k_index >= 0 && k_index < assetListCount {
  375. let indexPath = IndexPath(item: k_index, section: 0)
  376. indexPaths.append(indexPath)
  377. }
  378. }
  379. let collectionView = view.collectionView
  380. collectionView.performBatchUpdates({
  381. collectionView.reloadItems(at: indexPaths)
  382. }, completion: nil)
  383. } else {
  384. let collectionView = view.collectionView
  385. let assetList = _selectedAlbum!.assetList
  386. if needUpdateSingleType {
  387. for k_itemModel in assetList {
  388. k_itemModel.isLoseFocus = false
  389. }
  390. collectionView.reloadData()
  391. } else if needUpdateFocus {
  392. var indexPaths = Array<IndexPath>()
  393. for (i, k_itemModel) in assetList.enumerated() {
  394. let ok = isSingleType ? (assetMediaType == k_itemModel.asset.mediaType) : true
  395. if (ok && k_itemModel.isLoseFocus) {
  396. k_itemModel.isLoseFocus = false
  397. let indexPath = IndexPath(item: i, section: 0)
  398. indexPaths.append(indexPath)
  399. }
  400. }
  401. collectionView.performBatchUpdates({
  402. collectionView.reloadItems(at: indexPaths)
  403. }, completion: nil)
  404. }
  405. }
  406. let albumNavigationView = view.albumNavigationView
  407. albumNavigationView.nextButton.isEnabled = selectedAssetArray.count > 0
  408. if selectedAssetArray.count <= 0 {
  409. _currentSingleType = nil
  410. }
  411. return 0
  412. }
  413. public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  414. return _selectedAlbum?.assetList.count ?? 0
  415. }
  416. public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  417. var itemModel = _selectedAlbum?.assetList[indexPath.item]
  418. let mediaType = itemModel?.asset.mediaType
  419. let isPictureCell = mediaType == .image
  420. let iden = isPictureCell ? KSMediaPickerController.k_image_item_iden : KSMediaPickerController.k_video_item_iden
  421. let cell = collectionView.dequeueReusableCell(withReuseIdentifier: iden, for: indexPath) as! KSMediaPickerViewImageCell
  422. if cell.didSelectedItem == nil {
  423. cell.didSelectedItem = {[weak self] (collectionViewCell) -> UInt in
  424. return self?._didClickCell(collectionViewCell: collectionViewCell) ?? 0
  425. }
  426. cell.isMultipleSelected = maxItemCount > 1
  427. }
  428. if _currentSingleType != nil {
  429. if _selectedAssetArray.count > 0 {
  430. if _currentSingleType == .video {
  431. for itemModel1 in _selectedAssetArray {
  432. if itemModel?.asset.localIdentifier == (itemModel1 as! KSMediaPickerItemModel).asset.localIdentifier {
  433. itemModel = itemModel1 as? KSMediaPickerItemModel
  434. itemModel?.isLoseFocus = false
  435. }else {
  436. itemModel?.isLoseFocus = true
  437. }
  438. }
  439. }else if _currentSingleType == .picture {
  440. if mediaType == .video {
  441. itemModel?.isLoseFocus = true
  442. }else {
  443. // if _selectedAssetArray.count == maxPictureItemCount {
  444. // for itemModel1 in _selectedAssetArray {
  445. // if itemModel?.asset.localIdentifier == (itemModel1 as! KSMediaPickerItemModel).asset.localIdentifier {
  446. // itemModel = itemModel1 as? KSMediaPickerItemModel
  447. // itemModel?.isLoseFocus = false
  448. // }else {
  449. // itemModel?.isLoseFocus = true
  450. // }
  451. // }
  452. // }else {
  453. // for itemModel1 in _selectedAssetArray {
  454. // if itemModel?.asset.localIdentifier == (itemModel1 as! KSMediaPickerItemModel).asset.localIdentifier {
  455. // itemModel = itemModel1 as? KSMediaPickerItemModel
  456. // }
  457. // }
  458. // }
  459. }
  460. }
  461. }else {
  462. itemModel?.isLoseFocus = false
  463. }
  464. }else {
  465. itemModel?.isLoseFocus = false
  466. }
  467. // 3.0s以下视频不可选择
  468. if mediaType == .video {
  469. let duration = Double(itemModel?.asset.duration ?? 0)
  470. if duration < 3.0 {
  471. itemModel?.isLoseFocus = true
  472. }
  473. }
  474. cell.itemModel = itemModel
  475. return cell
  476. }
  477. private var _highlightedItemIndexPath: IndexPath?
  478. public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
  479. collectionView.deselectItem(at: indexPath, animated: true)
  480. _updateHighlightItem(at: indexPath)
  481. }
  482. private func _updateHighlightItem(at indexPath: IndexPath) {
  483. let view = self.view as! KSMediaPickerView
  484. guard indexPath != _highlightedItemIndexPath,
  485. let cell = view.collectionView.cellForItem(at: indexPath) as? KSMediaPickerViewImageCell,
  486. let itemModel = cell.itemModel,
  487. !itemModel.isLoseFocus else {
  488. return
  489. }
  490. let isStandard = _selectedAssetArray.count == 0 || itemModel == (_selectedAssetArray.firstObject as! KSMediaPickerItemModel)
  491. let previewView = view.previewView
  492. previewView.set(itemModel: itemModel, isStandard: isStandard)
  493. ///滚动至选择item区域
  494. let collectionView = view.collectionView
  495. let top = collectionView.contentInset.top
  496. var frame = collectionView.frame
  497. frame.origin.y = top
  498. frame.size.height -= top
  499. let cellFrame = cell.frame
  500. let frameInSuper = collectionView.convert(cellFrame, to: view)
  501. if !frame.contains(frameInSuper) {
  502. var point = CGPoint(x: 0.0, y: cellFrame.origin.y-top)
  503. let contentSizeHeight = collectionView.contentSize.height
  504. if cellFrame.maxY >= contentSizeHeight {
  505. point.y = contentSizeHeight-collectionView.bounds.size.height
  506. }
  507. collectionView.setContentOffset(point, animated: true)
  508. }
  509. ///滚动至选择item区域end
  510. view.showPreview(true)
  511. _updateHighlightedItemStatus()
  512. itemModel.isHighlight = true
  513. cell.itemIsHighlight = true
  514. _highlightedItemIndexPath = indexPath
  515. }
  516. private func _updateHighlightedItemStatus() {
  517. guard let indexPath = _highlightedItemIndexPath else {
  518. return
  519. }
  520. let highlightedItemModel: KSMediaPickerItemModel
  521. let highlightedCell = (view as! KSMediaPickerView).collectionView.cellForItem(at: indexPath) as? KSMediaPickerViewImageCell
  522. if highlightedCell == nil {
  523. highlightedItemModel = _selectedAlbum!.assetList[indexPath.item]
  524. } else {
  525. highlightedItemModel = highlightedCell!.itemModel
  526. highlightedCell?.itemIsHighlight = false
  527. }
  528. highlightedItemModel.isHighlight = false
  529. }
  530. }
  531. extension KSMediaPickerController {
  532. open class func authorityCheckUp(controller: UIViewController, type: KSMediaPickerController.mediaType, completionHandler: @escaping ((KSMediaPickerController.mediaType) -> Void), cancelHandler: ((UIAlertAction) -> Void)?) {
  533. switch type {
  534. case .picture:
  535. let authorization = {(status: PHAuthorizationStatus) in
  536. switch status {
  537. case .authorized:
  538. completionHandler(type)
  539. break
  540. case .denied:
  541. authorityAlert(controller: controller, name: "照片", cancelHandler: cancelHandler)
  542. break
  543. default:
  544. break
  545. }
  546. }
  547. let status = PHPhotoLibrary.authorizationStatus()
  548. if status == .notDetermined {
  549. PHPhotoLibrary.requestAuthorization(authorization)
  550. } else {
  551. authorization(status)
  552. }
  553. break
  554. case .video:
  555. let authorization = {(granted: Bool) in
  556. if granted {
  557. completionHandler(type)
  558. } else {
  559. authorityAlert(controller: controller, name: "照相机", cancelHandler: cancelHandler)
  560. }
  561. }
  562. let mediaType = AVMediaType.video
  563. let status = AVCaptureDevice.authorizationStatus(for: mediaType)
  564. if status == .notDetermined {
  565. AVCaptureDevice.requestAccess(for: mediaType, completionHandler: authorization)
  566. } else {
  567. authorization(status == .authorized)
  568. }
  569. break
  570. default :
  571. break
  572. }
  573. }
  574. open class func authorityAlert(controller: UIViewController, name: String, cancelHandler: ((UIAlertAction) -> Void)?) {
  575. let bundle = Bundle.main
  576. let appName = NSLocalizedString("CFBundleDisplayName", tableName: "InfoPlist", bundle: bundle, comment: "")
  577. let title = "没有打开“\(appName)”访问权限"
  578. let message = "请进入“设置”-“\(appName)”打开\(appName)开关"
  579. let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
  580. let go = UIAlertAction(title: "去设置", style: .default) { (action) in
  581. let application = UIApplication.shared
  582. let url = URL(string: UIApplication.openSettingsURLString)!
  583. if application.canOpenURL(url) {
  584. if #available(iOS 10.0, *) {
  585. application.open(url, options: [.universalLinksOnly: false], completionHandler: nil)
  586. } else {
  587. application.openURL(url)
  588. }
  589. if cancelHandler != nil {
  590. cancelHandler!(action)
  591. }
  592. }
  593. }
  594. alert.addAction(go)
  595. let cancel = UIAlertAction(title: "取消", style: .cancel, handler: cancelHandler)
  596. alert.addAction(cancel)
  597. controller.present(alert, animated: true, completion: nil)
  598. }
  599. open class func authorityAudioCheckUp(controller: UIViewController, completionHandler: @escaping (() -> Void), cancelHandler: ((UIAlertAction) -> Void)?) {
  600. let authorization = {(granted: Bool) in
  601. if granted {
  602. completionHandler()
  603. } else {
  604. authorityAlert(controller: controller, name: "麦克风", cancelHandler: cancelHandler)
  605. }
  606. }
  607. let mediaType = AVMediaType.audio
  608. let status = AVCaptureDevice.authorizationStatus(for: mediaType)
  609. if status == .notDetermined {
  610. AVCaptureDevice.requestAccess(for: mediaType, completionHandler: authorization)
  611. } else {
  612. authorization(status == .authorized)
  613. }
  614. }
  615. }
  616. extension KSMediaPickerController : UITableViewDelegate, UITableViewDataSource {
  617. public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  618. return _albumList?.count ?? 0
  619. }
  620. private static let k_iden = "KSMediaPickerViewAlbumCell"
  621. public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  622. let iden = KSMediaPickerController.k_iden
  623. var cell = tableView.dequeueReusableCell(withIdentifier: iden) as? KSMediaPickerViewAlbumCell
  624. if cell == nil {
  625. cell = KSMediaPickerViewAlbumCell(style: .subtitle, reuseIdentifier: iden)
  626. }
  627. cell?.albumModel = _albumList?[indexPath.row]
  628. cell?.indexPath = indexPath
  629. cell?.count = Int(self.curSelectCount)
  630. return cell!
  631. }
  632. public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  633. let cell = tableView.cellForRow(at: indexPath) as? KSMediaPickerViewAlbumCell
  634. tableView.deselectRow(at: indexPath, animated: true)
  635. guard cell != nil, let albumModel = cell?.albumModel else {
  636. return
  637. }
  638. _selectedAlbum = albumModel
  639. _chengedAlbumListStatus((view as! KSMediaPickerView).albumNavigationView.centerButton)
  640. }
  641. }
  642. // MARK: - JXSegmentedDelegate
  643. extension KSMediaPickerController : JXSegmentedListContainerViewListDelegate {
  644. public func listView() -> UIView {
  645. return view
  646. }
  647. public func listDidAppear() {
  648. (view as! KSMediaPickerView).previewView.videoPlay()
  649. }
  650. public func listDidDisappear() {
  651. (view as! KSMediaPickerView).previewView.videoPause()
  652. }
  653. }