iOS開発メモ7 (MediaUploaderの開発3)

関連する過去の投稿

iOS開発メモ6 (MediaUploaderの開発2)
iOS開発メモ5 (MediaUploaderの開発1)
iOS開発メモ4 (MediaUploaderの設計)

今回はセルの描画について検討する。

既に前回までの実装で、セルに写真ロールのイメージを貼り付けるところまでは完了している。そのときは細かい内容はさらっと流したが、画像をbackgroundViewにUIImageViewを使って設定している。

UICollectionViewCellには、backgroundView, selectedBackgroundView, contentViewの3つのビューを保持している。それらが透明なレイヤのように重なっており、選択したときだけselectedBackgroundViewが表示されるような挙動が、CollectionViewには備わっている。

CollectionViewCell

MediaUploaderでは、CollectionViewで写真を選択してアップロードするが、既にアップロード済みのデータを何かしらの方法で記憶しておいて、チェックをつけておきたい。(UIView.isOpaqueで表示と非表示を切り替える?)

それらを実現するため、以下のようなビューの構成で実装してみる。(これがベストな方法かどうかは、よくわからない)

CollectionViewCell2

うまくいけば、下図の様に切り替えられるはずである。

CollectionViewCell3

CollectionViewのセルの実装

まず、CollectionViewに対して、複数選択を許可する。
(インタフェースビルダーで設定できるならそれでも良い)

class FirstViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 複数選択プロパティ
        collectionView.allowsMultipleSelection = true
        :
    }
    :
}

次に選択ON/OFFを表示する丸印のビューを、UIViewを継承したSelectIconViewとして作成する。イニシャライザで選択状態のフラグを入力できるようにして、draw()で描画されるときに選択ONのときに塗りつぶすようにする。draw()内で、ベジェツールを使って頑張って丸を描く。

import UIKit

class SelectIconView: UIView {
    
    var selected : Bool = false
    
    required init?(coder aDecoder: NSCoder){
        super.init(coder: aDecoder)
    }
    
    init(frame: CGRect,selected: Bool) {
        super.init(frame:frame)
        self.backgroundColor = UIColor.clear
        self.selected = selected
    }
    
    override func draw(_ rect: CGRect) {
        
        let x = rect.width - (rect.width/3) / 2
        let y = rect.height - (rect.height/4) / 2 - 5
        let r = (rect.height/4) / 2
        let thickness = 4.0
        
        UIColor.gray.setStroke()
        UIColor.yellow.setFill()
        
        // circle
        let arc = UIBezierPath( arcCenter: CGPoint(x: x, y: y ),
            radius: r,  startAngle: 0,
            endAngle: CGFloat( Double.pi * 2 ), clockwise: true)
        arc.lineWidth = CGFloat(thickness)
        
        arc.stroke()
        
        if( self.selected == true ){
            arc.fill()
        }
    }
    
}

cellForItemAtでbackgroundViewにUIImageViewを設定する処理を全開実装したが、この続きでSelectionIconViewを未選択状態のもの(selected:false)と、選択状態のもの(selected:true)を生成して、前述した設計どおりにビューを設定する。

extension FirstViewController : UICollectionViewDataSource {
    // cellForItemAt
    func collectionView(_ collectionView: UICollectionView,
        cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        :
        imageManager.requestImage( for: asset, targetSize: thumbnailSize,
            contentMode: .aspectFill, options: nil, resultHandler: {
            (image, info) in
                if cell.assetIdentifier == asset.localIdentifier {
                
                    let bkImageView : UIImageView
                    bkImageView = cell.backgroundView as! UIImageView
                    bkImageView.image = image
                    
                    // 未選択状態のアイコンをサブビューとして追加
                    let subView = SelectIconView(frame:cell.bounds, selected:false)
                    cell.backgroundView?.addSubview(subView)
                    
                    // 選択状態のアイコンをselectedBackgroundViewに設定
                    let selView = SelectIconView(frame:cell.bounds, selected:true)
                    cell.selectedBackgroundView = selView
                }
        })
        
        return cell
    }
}

ここまで実装したらシミュレータで実行してみる。起動後、すべての写真セルに丸印が描画されていることを確認する。

ss--2017-10-26-9.27.58

次にセルをタップすると、丸印が塗りつぶされた選択状態に変化すること、複数選択状態にしたり解除できることができるはず。

ss--2017-10-26-9.28.12

※アップロード済みを示すアイコンの実装は、後日データ管理の実装時に行うので保留とする。

次回は、写真のメタ情報の取得についてまとめる。