Swift 自定義圖片選擇器(三) -- 圖片展示界面

多選圖片

首先來分析一下界面的交互:

  • 導(dǎo)航欄設(shè)置了返回按鈕和右邊的確定按鈕。點(diǎn)擊確定按鈕則將選中的照片返回。
  • 可以設(shè)置最多可勾選張數(shù)maxCount, 如果勾選超過maxCount則彈出提示框。
  • 勾選時,選中的照片顯示勾選圖標(biāo),并且添加一層蒙版。取消勾選時,顯示可勾選的空心圈圈,并去掉蒙版。
  • 點(diǎn)擊照片可以顯示該圖片的大圖

實(shí)現(xiàn)

使用UICollectionView, 每行4列,根據(jù)屏幕的大小計(jì)算出照片的寬度,高度與寬度一致,得出UICollectionViewCell的itemSize.
class PickImageViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
private var collectionView : UICollectionView?
private let CellIdentifier = "ImageCollectionCellIdentifier"
/// 獲取相冊相關(guān)的class
private let imageHelper = PickerHelper.helperDefault
private var pictures = [PictureItem]()  // 保存當(dāng)前相冊所有的圖片資源
var albumItem: AlbumItem?   // 相冊資源
var selectedPictures = [PictureItem]()  // 選中的圖片資源
}

在viewDidLoad中創(chuàng)建collectionView,并獲取根據(jù)albumItem獲取圖片資源,保存到pictures,pictures就是collectionView的數(shù)據(jù)源

/// 創(chuàng)建collectionView
private func initCollectionView() {
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: width, height: width)
    layout.minimumLineSpacing = lineSpace
    layout.minimumInteritemSpacing = lineSpace
    layout.sectionInset = UIEdgeInsets.init(top: insetSpace, left: insetSpace, bottom: insetSpace, right: insetSpace)
    
    collectionView = UICollectionView(frame: UIScreen.main.bounds, collectionViewLayout: layout)
    collectionView!.backgroundColor = UIColor.white
    collectionView?.delegate = self
    collectionView?.dataSource = self
    //注冊cell
    collectionView!.register(ImageCollectionCell.self, forCellWithReuseIdentifier: CellIdentifier)
    self.view.addSubview(collectionView!)
}

/// 獲取圖片資源
private func getPictures() {
    // MARK: 獲取全部圖片
    if self.albumItem == nil {
        return
    }
    
    let array = imageHelper.getPicturesInAlbumItem(self.albumItem!)
    pictures += array
    
    //將之前選中的圖片在全部圖片中勾選上
    self.setPictureSelected()
    
    collectionView!.reloadData()
}
ImageCollectionCell UICollectionViewCell的子類,根據(jù)一個PictureItem顯示一張圖片。
class ImageCollectionCell: UICollectionViewCell {
private let showImageView =  UIImageView()
private let selectButton = UIButton()
private let imageMaskView = UIView()
private var isSelectedImage = false
private var picturnItem: PictureItem?  // 顯示的圖片資源
var block : (_ isSelected: Bool) -> () = {_ in }  // 勾選或者取消勾選時,通知controller

// 沒有使用xib或者storyboard所以需要重載init方法
override init(frame: CGRect) {
    super.init(frame: frame)
    self.initView()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

設(shè)置cell 的內(nèi)容, 顯示的是小圖,并且獲取大圖保存起來(點(diǎn)擊縮略圖時顯示大圖,所以就一并獲?。?。

/// 設(shè)置cell的內(nèi)容
///
/// - parameter item:         圖片資源
/// - parameter selectAction: 勾選、取消勾選的操作
func setCellPictureItem(_ item: PictureItem, selectAction: @escaping (_ isSelected: Bool) -> ()) {
    self.picturnItem = item
    block = selectAction
    
    if item.lowImage != nil {
        showImageView.image = item.lowImage
    }
    else {
        // 沒有小圖,則根據(jù)asset資源獲取圖片的縮略圖
        PickerHelper.helperDefault.getImageWithAsset(item.asset, size: self.bounds.size, finishedCallack: { (image) in
            item.lowImage = image
            self.showImageView.image = image
        })
    }
    
    if item.hightImage == nil {
        // 獲取大圖
        PickerHelper.helperDefault.getImageWithAsset(item.asset, size: PickerHelper.helperDefault.targetSize, finishedCallack: { (image) in
            item.hightImage = image
        })
    }
    
    setSelectButton(item.isSelected)
}

勾選、取消勾選的時候添加、移除蒙版,蒙版要添加在勾選按鈕下面,這樣才不會影響勾選按鈕的點(diǎn)擊響應(yīng)。

/// 選中或取消選中時更新界面方法
///
/// - parameter isSelected: 是否選中的標(biāo)志
private func setSelectButton(_ isSelected: Bool) {
    if isSelected {
        //當(dāng)前選中, 則添加一層蒙版
        self.insertSubview(imageMaskView, belowSubview: selectButton)
    }
    else {
        imageMaskView.removeFromSuperview()
    }
    // 設(shè)置勾選按鈕的狀態(tài),按鈕會自動更改圖片
    selectButton.isSelected = isSelected;
}

/// 取消選中,主要是給多選了之后,重置用的
public func setCellUnSelected() {
    self.picturnItem?.isSelected = false
    setSelectButton(false)
 }

需要以下設(shè)置,按鈕才能根據(jù)自身的狀態(tài)更改圖片

selectButton.setImage(UIImage.init(named: "store_picture_unselected"), for: .normal)
selectButton.setImage(UIImage.init(named: "store_picture_selected"), for: .selected)

在cellForItemAtIndexPath 設(shè)置cell的內(nèi)容

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let row = indexPath.row
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellIdentifier, for: indexPath) as! ImageCollectionCell
    let pictureItem = pictures[row]
    
    cell.setCellPictureItem(pictureItem, selectAction: { (isSelectedImage) in
        // 勾選、取消勾選后執(zhí)行的操作
        var isSelectedCell = true
        
        if isSelectedImage {
            // 勾選,則判斷是否超過maxCount
            isSelectedCell = self.checkMaxCount(cell)
        }
        
        //只有沒有超出maxCount才會勾選,添加到選擇數(shù)組里
        if (isSelectedCell) {
            self.setImageSelectedInRow(row, isSelected: isSelectedImage)
        }
    })

    return cell
}

判斷已經(jīng)勾選的數(shù)量是否大于maxCount。無論有沒有超出maxCount,cell都會默認(rèn)先勾選了。如果已經(jīng)超出范圍時,需要取消勾選。

/// 判斷選中數(shù)量是否超出可勾選的數(shù)值
///
/// - parameter cell: cell
///
/// - returns: 是否超出范圍 true: 沒有,false: 超出
private func checkMaxCount(_ cell: ImageCollectionCell) -> Bool {
    if selectedPictures.count >= PickerHelper.helperDefault.maxCount {
        // 取消勾選 (因?yàn)闊o論有沒有超出maxCount,cell都會默認(rèn)先勾選了。所以超出范圍時,需要取消)
        cell.setCellUnSelected()
        
        //顯示提示
        let alert = UIAlertController(title: "溫馨提示", message: "最多只能選\(PickerHelper.helperDefault.maxCount)張", preferredStyle: .alert)
        
        let cancelAction = UIAlertAction(title: "確定", style: .default, handler: nil)
        alert.addAction(cancelAction)
        
        self.present(alert, animated: true, completion: nil)
        
        return false
    }
    
    // 沒有超出范圍
    return true
}

如果是沒有超出maxCount的勾選,則將圖片添加到已選數(shù)組。如果是取消勾選,則在已選數(shù)組中移除。

/// 選中或者取消選中方法
///
/// - parameter row:        圖片的下標(biāo)
/// - parameter isSelected: 是否選中的標(biāo)志
private func setImageSelectedInRow(_ row: Int, isSelected: Bool) {
    let item = pictures[row]
    
    if isSelected {
        //添加到選中數(shù)組
        if self.selectedPictures.contains(item) == false {
            self.selectedPictures.append(item)
        }
    }
    else {
        if self.selectedPictures.contains(item) == true {
            let curIndex = self.selectedPictures.index(of: item)!
            self.selectedPictures.remove(at: curIndex)
        }
    }
}

獲取照片庫的授權(quán)權(quán)限

想要訪問相冊,首先的獲得系統(tǒng)的授權(quán)。在app的配置文件info.plist中添加一下項(xiàng):(添加相冊項(xiàng)即可)


info配置

然后獲取相冊授權(quán)狀態(tài),如果你的app沒有進(jìn)行過授權(quán)的話,是授權(quán)狀態(tài)一般是.notDetermined,此時需要請求授權(quán)。

// MARK: 相冊授權(quán)相關(guān)
private func getPhotoLibraryAuthorization() -> Bool {
    let authorizationStatus = PHPhotoLibrary.authorizationStatus()

    switch authorizationStatus {
    case .authorized:
        print("已經(jīng)授權(quán)")
        return true
    case .notDetermined:
        print("不確定是否授權(quán)")
        // 請求授權(quán)
        PHPhotoLibrary.requestAuthorization({ (status) in })
    case .denied:
        print("拒絕授權(quán)")
    case .restricted:
        print("限制授權(quán)")
        break
    }
    
    return false
}

顯示Pikcer圖片選擇器

將跳轉(zhuǎn)到Picker的方法封裝在PickerHelper中,然后用戶就可以調(diào)用這個方法直接使用Pikcer

/// 顯示圖片選擇界面
///
/// - parameter viewController:  上一個界面
/// - parameter selectePictures: 已選圖片
/// - parameter maxCount:        最多選擇張數(shù)
/// - parameter selectedAction:  選擇圖片返回block
func showPhotoPickerInController(_ viewController: UIViewController, selectePictures: [PictureItem]?, maxCount count: Int, targetSize size: CGSize, selectedAction: @escaping ([PictureItem]?) -> ()) {
    maxCount = count
    targetSize = size

    if self.getPhotoLibraryAuthorization() {
        // 主要解決:已經(jīng)選中的圖片,取消選中了之后,沒有確定,而是取消選擇時,isSelected會在取消選中時置為false的問題
        for (_, item) in (selectePictures?.enumerated())! {
            item.isSelected = true
        }
        
        //授權(quán)可以訪問相冊
        let albums = PickerHelper.helperDefault.getSmartAlbums()
        
        if albums == nil {
            return
        }
        // 選擇第一個相冊顯示
        let albumItem = albums![0]
        // 圖片選擇
        let picker = PickImageViewController()
        picker.albumItem = albumItem
        picker.completeBlock = { (pictures, isSureButtonTouch) in
            if isSureButtonTouch {
                //只有點(diǎn)擊了確定按鈕返回的數(shù)據(jù)才是最后確定選擇的
                selectedAction(pictures)
            }
        }

        //設(shè)置已選中圖片
        if selectePictures != nil {
            picker.selectedPictures = selectePictures!
        }
       // 跳轉(zhuǎn)到picker
        viewController.navigationController?.pushViewController(picker, animated: true)
    }
    else if PHPhotoLibrary.authorizationStatus() != .notDetermined {
        // 用戶明確拒絕授權(quán)后,提示用戶在設(shè)置中修改
        let alert = UIAlertController(title: "溫馨提示", message: "沒有相冊的訪問權(quán)限,請?jiān)趹?yīng)用設(shè)置中開啟權(quán)限", preferredStyle: .alert)
        
        let cancelAction = UIAlertAction(title: "確定", style: .cancel, handler: nil)
        alert.addAction(cancelAction)
        
        viewController.present(alert, animated: true, completion: nil)
    }
}

用戶調(diào)用Picker

PickerHelper.helperDefault.showPhotoPickerInController(self, selectePictures: self.selectePictures, maxCount: 4, targetSize: .zero)  { (pictures) in
  self.selectePictures = pictures!
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,406評論 4 61
  • 1)清除參考線--- 視圖->清除參考線 2)切圖-----------圖層->基于圖層的切片1,使用切片工具Pa...
    huhu502閱讀 387評論 1 0
  • 窗外淅淅瀝瀝的雨滴聲聲入耳, 不,那不是雨,是天空的眼淚, 多少個輾轉(zhuǎn)難眠的夜晚, 無法言說的苦楚, 難以抑制的思...
    行走的木木閱讀 221評論 0 0
  • 曾有調(diào)查顯示,人的皮膚與服裝之間產(chǎn)生的瞬間靜電最高可達(dá)上萬伏;人在地毯上走動可產(chǎn)生1500~35000伏靜電;在室...
    鄰居知道閱讀 33,280評論 1 1
  • 安妮寶貝曾說:不知道小說里的少年藤井樹,會不會是巖井俊二寫給自己的一個映照。散漫懶惰,不善于和人打交道。特立獨(dú)行卻...
    阿花呀_閱讀 741評論 0 1

友情鏈接更多精彩內(nèi)容