【徒然iOS】気ままにUIKit99〜Collection View Controller レイアウト変更をアニメーション〜
概要
このマガジンは四十を過ぎたおっさんが、
を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。
今回
をハイ、レッツゴ🕺
前準備
念の為、
バックアップ
をいつも通りやってから本題へ💃
本題
とりあえず、サイト記事をザッと見ると、
カスタムクラスを書き換えていってるだけ感
なので、まずは、恒例の一覧表で整理する〜〜〜🕺
一覧表
ひとつひとつ試してみよう🕺
⒈事前準備
でやったビューを新規で追加して、カスタムクラスを組み替えていく手順で、ひとつひとつ検証してみよう
(流石にビューを全て増やすのはちょっと効率が悪すぎるので💦)
class MyCollectionAnimationViewController: UICollectionViewController {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
}
//データの個数を返すメソッド
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 7
}
//データを返すメソッド
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//セルを取得し、イメージビューに画像を設定して返す。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionCell", for: indexPath as IndexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
return cell
}
//セル選択時の呼び出しメソッド
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//セグエを実行する。
performSegue(withIdentifier: "MySegue", sender: nil)
}
//画面遷移実行前の呼び出しメソッド
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//選択中のセルの画像を取得する。
let index = collectionView?.indexPathsForSelectedItems?.first
let cell = collectionView?.cellForItem(at: index!)
let imageView = cell!.viewWithTag(1) as! UIImageView
//遷移先のビューコントローラーを取得し、インスタンス変数に画像とテキストを設定する。
let controller: CollectionAnimationViewController = (segue.destination as? CollectionAnimationViewController)!
controller.myTitle = String(index!.row + 1)
controller.myImage = imageView.image
}
}
今回はこのコードを色々、書き換えるみたいなので、
以降は、大項目ごとに説明してく〜〜〜
clearsSelectionOnViewWillAppearプロパティ
//データを返すメソッド
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
//セルを取得し、イメージビューに画像を設定して返す。
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCell", forIndexPath: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
//セル選択時の背景色を設定する。
let selectedView = UIView()
selectedView.backgroundColor = UIColor.redColor();
cell.selectedBackgroundView = selectedView;
return cell
}
コードを見ると、
中身を書き換えればいいみたいなので〜〜〜
installsStandardGestureForInteractiveMovementプロパティ
useLayoutToLayoutNavigationTransitionsプロパティ
なんかもうひとつクラスを増やさないといけないみたいだから、
//
// TestCollectionViewController2.swift
//
import UIKit
class TestCollectionViewController2: UICollectionViewController {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//レイアウトの変更
if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout{
//画像サイズと画面サイズを同じにし、スペースを無くす。
let width = floor(collectionView!.bounds.width)
layout.itemSize = CGSizeMake(width, width)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
}
を参考にコードを追加して、コイツ用のクラスを増やす
//
// TestCollectionViewController.swift
//
import UIKit
class TestCollectionViewController: UICollectionViewController {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.whiteColor()
//clearsSelectionOnViewWillAppear = false
}
//データの個数を返すメソッド
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
//データを返すメソッド
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
//セルを取得し、イメージビューに画像を設定して返す。
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCell", forIndexPath: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
//セル選択時の背景色を設定する。
let selectedView = UIView()
selectedView.backgroundColor = UIColor.redColor();
cell.selectedBackgroundView = selectedView;
return cell
}
//セル選択時の呼び出しメソッド
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
//レイアウト変更用のコレクションビューコントローラーのインスタンスをナビゲーションコントローラーにpushする。
let controller = TestCollectionViewController2(collectionViewLayout:UICollectionViewFlowLayout())
controller.useLayoutToLayoutNavigationTransitions = true;
navigationController!.pushViewController(controller, animated: true)
}
}
を参考に増やした元クラスを書き換え〜〜〜
レイアウトを連続で変更する。
//
// TestCollectionViewController.swift
//
import UIKit
//レイアウト変更残回数
var count:CGFloat = 7.0
class TestCollectionViewController: UICollectionViewController, UINavigationControllerDelegate {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.whiteColor()
clearsSelectionOnViewWillAppear = false
//画面幅をレイアウト変更残回数で割った値を画像サイズにする。
let width = floor(self.collectionView!.bounds.width / count--)
//レイアウトの変更
if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout{
//スペースを無くす。
layout.itemSize = CGSizeMake(width, width)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
//データの個数を返すメソッド
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
//データを返すメソッド
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
//セルを取得し、イメージビューに画像を設定して返す。
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("TestCell", forIndexPath: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
//セル選択時の背景色を設定する。
let selectedView = UIView()
selectedView.backgroundColor = UIColor.redColor();
cell.selectedBackgroundView = selectedView;
return cell
}
//セル選択時の呼び出しメソッド
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if(count > 0) {
//自クラスのインスタンスを作り、ナビゲーションコントローラーにpushする。
let controller = TestCollectionViewController(collectionViewLayout:UICollectionViewFlowLayout())
controller.useLayoutToLayoutNavigationTransitions = true;
navigationController!.pushViewController(controller, animated: true)
}
}
//ビューコントローラー追加削除時の呼び出しメソッド
override func didMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
//削除(戻るボタンが押された)の場合はレイアウト変更残回数をインクリメントする。
count++
}
}
}
を参考に書き換えて動かしてみたけど、
オペランド値でデクリメントとインクリメントをしているので、
Swift3以降では使えないから当たり前〜〜〜
コードまとめ
clearsSelectionOnViewWillAppearプロパティ、installsStandardGestureForInteractiveMovementプロパティ
class MyCollectionAnimationViewController: UICollectionViewController {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//clearsSelectionOnViewWillAppearプロパティ:clearsSelectionOnViewWillAppearプロパティをfalseに設定して選択を解除しない
collectionView?.backgroundColor = UIColor.white
//ビューが表示されるときに選択を解除しない設定にする。
clearsSelectionOnViewWillAppear = false
}
//データの個数を返すメソッド
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 7
}
//データを返すメソッド
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//clearsSelectionOnViewWillAppearプロパティ:ビューが表示されるときにテーブルの選択を解除する(true)、または、解除しない(false)を設定するプロパティ。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionCell", for: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
//セル選択時の背景色を設定する。
let selectedView = UIView()
selectedView.backgroundColor = UIColor.red;
cell.selectedBackgroundView = selectedView;
return cell
}
//セル選択時の呼び出しメソッド
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//セグエを実行する。
performSegue(withIdentifier: "MySegue", sender: nil)
}
//画面遷移実行前の呼び出しメソッド
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//選択中のセルの画像を取得する。
let index = collectionView?.indexPathsForSelectedItems?.first
let cell = collectionView?.cellForItem(at: index!)
let imageView = cell!.viewWithTag(1) as! UIImageView
//遷移先のビューコントローラーを取得し、インスタンス変数に画像とテキストを設定する。
let controller: CollectionAnimationViewController = (segue.destination as? CollectionAnimationViewController)!
controller.myTitle = String(index!.row + 1)
controller.myImage = imageView.image
}
//installsStandardGestureForInteractiveMovementプロパティ:セルの並び替えを行うためのジェスチャーリコグナイザーをインストールする(true)、しない(false)を設定するプロパティ。
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
print("移動元インデックス番号 \(sourceIndexPath.row)")
print("移動先インデックス番号 \(destinationIndexPath.row)")
}
}
useLayoutToLayoutNavigationTransitionsプロパティ
//useLayoutToLayoutNavigationTransitionsプロパティ:このプロパティをtrueにするとコレクションビューのレイアウトをアニメーションさせながら変更できるようになる。
class MyAnimationCollectionViewController: UICollectionViewController {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
//レイアウトの変更
if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout{
//画像サイズと画面サイズを同じにし、スペースを無くす。
let width = floor(collectionView!.bounds.width)
layout.itemSize = CGSizeMake(width, width)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
}
//MyAnimationCollectionViewController用のクラス
class MyCollectionAnimation2ViewController: UICollectionViewController {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.white
//clearsSelectionOnViewWillAppear = false
}
//データの個数を返すメソッド
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
//データを返すメソッド
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//セルを取得し、イメージビューに画像を設定して返す。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionCell", for: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
//セル選択時の背景色を設定する。
let selectedView = UIView()
selectedView.backgroundColor = UIColor.red;
cell.selectedBackgroundView = selectedView;
return cell
}
//セル選択時の呼び出しメソッド
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//レイアウト変更用のコレクションビューコントローラーのインスタンスをナビゲーションコントローラーにpushする。
let controller = MyAnimationCollectionViewController(collectionViewLayout:UICollectionViewFlowLayout())
controller.useLayoutToLayoutNavigationTransitions = true;
navigationController!.pushViewController(controller, animated: true)
}
}
レイアウトを連続で変更する:使えないけど、これだとNGってサンプルも参考になるだろうから載せとく〜〜〜〜
//レイアウト変更残回数
var count:CGFloat = 7.0
//レイアウトを連続で変更する:使えない
class MyRepeatAnimationCollectionViewController: UICollectionViewController, UINavigationControllerDelegate {
//最初からあるメソッド
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.white
clearsSelectionOnViewWillAppear = false
//画面幅をレイアウト変更残回数で割った値を画像サイズにする。
let width = floor(self.collectionView!.bounds.width / count)
//レイアウトの変更
if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout{
//スペースを無くす。
layout.itemSize = CGSizeMake(width, width)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
//データの個数を返すメソッド
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
//データを返すメソッド
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//セルを取得し、イメージビューに画像を設定して返す。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCollectionCell", for: indexPath)
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
imageView.image = UIImage(named: "item" + String(indexPath.row) + ".png")
//セル選択時の背景色を設定する。
let selectedView = UIView()
selectedView.backgroundColor = UIColor.red;
cell.selectedBackgroundView = selectedView;
return cell
}
//セル選択時の呼び出しメソッド
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if(count > 0) {
//自クラスのインスタンスを作り、ナビゲーションコントローラーにpushする。
let controller = MyRepeatAnimationCollectionViewController(collectionViewLayout:UICollectionViewFlowLayout())
controller.useLayoutToLayoutNavigationTransitions = true;
navigationController!.pushViewController(controller, animated: true)
}
}
//ビューコントローラー追加削除時の呼び出しメソッド
override func didMove(toParent parent: UIViewController?) {
if parent == nil {
//削除(戻るボタンが押された)の場合はレイアウト変更残回数をインクリメントする。
count += 1
}
}
}
ブラッシュアップ
他は特に使わないので、最初のクラスに適用を戻す
AutoLayout〜〜〜
恒例の地球儀ボタン〜〜〜
記事公開後、
Apple公式
さて次回は、
をレッツゴする🕺