【iOS】画面の向きごとに違う画像を表示したかった
したかったこと
背景に画像を表示するViewControllerにおいて
- 縦画面と横画面で違う画像を表示したい
- あるトリガーで背景画像を変更したい
この2つを両立させようとしました
今回は例として、
- 縦画面で普通の茶トラ猫が、横画面でウインクをした茶トラ猫が背景画像に出現する
- ボタンを押すと茶トラ猫ではなくサバトラ猫に変更する
この用件で説明していきます
UIImageViewひとつで頑張る
アプローチ1 UIImageView
はレイアウトの制約と同様に画面サイズごとに異なる画像を設定できます
UIImageViewのインスペクタのImageの左にある+
を押すことで各画面サイズで表示する画像を設定できます
縦 | 横 |
---|---|
これでしたかったことの1つ目はクリアできました。では2つ目はどうでしょうか
画像の変更はコード上で行うしかありませんが、UIImageViewのOutletは画面の大きさごとには設定できません。すると以下の問題が発生します
- サバトラ猫に変更した後に画面を回転させると、元のStoryboardの設定が適用されて茶トラ猫に戻される
以上が解決できなさそうだったためこの方法は断念しました
UIImageViewをたくさん使って力技
アプローチ2 アプローチ1では1つ目の用件はクリアできたので、その要素を取り入れつつ2つ目を実現しました
単純にUIImageViewをもう一つ増やして、茶トラ猫とサバトラ猫を表示するビューを別にしてしまえば良いのです
以下は表示する猫を切り替えるコードの実装例です
import UIKit
final class ViewController: UIViewController {
/// 現在茶トラ猫が表示されているかどうか
private var isTyatora = true
/// 茶トラ猫を表示するUIImageView
@IBOutlet weak private var tyatoraImageView: UIImageView!
/// サバトラ猫を表示するUIImageView
@IBOutlet weak private var sabatoraImageView: UIImageView!
/// 茶トラ猫とサバトラ猫を切り替えるUIButtonのアクション
@IBAction private func catChangeButtonPressed(_ sender: UIButton) {
self.tyatoraImageView.isHidden = isTyatora
self.sabatoraImageView.isHidden = !isTyatora
self.isTyatora = !self.isTyatora
}
}
無事用件を満たすことはできました
しかしこの方法では以下のデメリットがあります
- UIImageViewを一つ多く保持するためメモリ使用量が増加する
- 猫の種類が増えた時に対応が大変になっていく(可読性の観点も踏まえて)
次の方法でこれらを解消できたため、個人的ベストアプローチとして紹介します
Asset Catalogを活用
マイベストアプローチ アプローチ1では、UIImageViewのimage
を画面サイズ別に設定することで画面が縦の時と横の時で別々の画像を表示しました
が、Asset Catalogから画像自体に各画面ごとの設定を行うことができました
やり方はレイアウトの時と同じです
- 画面サイズごとに出し分けたい画像の
Height Class
をAnyからAny & Compact
にして
- 出現した
Compact Height
に横画面の時の画像を設定する
今回の場合、茶トラ猫とサバトラ猫の画像両方に設定することで一つのUIImageViewの画像を変更するだけで縦横に対応した画像を変更することができます
以下は画像を切り返るコードの実装例です
import UIKit
final class ViewController: UIViewController {
/// 現在茶トラ猫が表示されているかどうか
private var isTyatora = true
/// 猫を表示するUIImageView
@IBOutlet weak private var catImageView: UIImageView!
/// 茶トラ猫とサバトラ猫を切り替えるUIButtonのアクション
@IBAction private func catChangeButtonPressed(_ sender: UIButton) {
let catName = self.isTyatora ? "sabatora_cat" : "tyatora_cat"
self.catImageView.image = UIImage(named: catName)
self.isTyatora = !self.isTyatora
}
}
UIImageViewは一つで済むため、猫の種類が増えても変数が増えることもありません
また、使用メモリ量もアプローチ2の時よりも減少しています
まとめ
Asset Catalog
はとても便利、と思うことが多いです
色と画像をAsset Catalogで設定しておくと、コード上…よりはStoryboard上でかなり便利になります
iOS始めたてのころは(参加したプロジェクトが)UIも全てコード上で記述していたため、Storyboardを利用するようになってからはいろいろと目から鱗でした
iOS/Swift2年目に突入し、初級者向けでもいいからアウトプットを起こそうかなと思い書いてみました
SwiftUIもかなり進化を遂げてきているので、そろそろ馴染ませていきたいなと思うこの頃です
Discussion