スポンサードリンク

アプリ編#10 ステータスバーを塗り塗り【SwiftUI】

スマートカーテン

やぎ星人です。どうもこんにちは。
最近「あれ、やぎ星人さん太った?」って言われることが増えて、凄く嫌です。
「今日はちょっとむくんでるだけです」とか「役作りです(キリッ」とか言って誤魔化してるんですけど、このやり取りがだんだん嫌になってきました。
なにか対処法はないですかね。良案募集中です。(痩せろ以外で)

さて、前回記事の続きをやっていきます。

やりたいことは至ってシンプルです。
ステータスバーの色を白→黒に変更します。

情報収集

課題解決の際はいつもそうなのですが、書籍やインターネットで情報を集めてみました。

1. PJ設定にて、Status Bar Styleの色を変更

Target->General->Deployment Infoより、Status Bar Styleの設定を変更することで、色変更ができるとのこと。Default → Dark ContentやLight Contentに変更してみました。
Dark Content・・・文字色を黒で固定
Light Content・・・文字色を白で固定

なんだ簡単じゃんと思ったのですが、結果としてはステータスバーの色や文字色は変わりませんでした..チクショー!

2. PJ設定にてStatus Bar Styleの設定を全ての画面に適用するよう変更 

Target->Info -> Custom iOS Target Propertiesに下記パラメータを追加すると、Status Bar Styleの設定がすべての画面に適用されるとのことでした。

Key->View controller-based status bar appearance
Value->NO

前述した対応(Status Bar Styleの設定値を変更)も行い、どう反映されるか確認してみました。
Status Bar Style:Light Content

おお!
ステータスバーの文字が白色に変更された!?
だが、肝心のステータスバー自体の色は白いまま。

ここからネット上で見つけた様々な方法を試してみましたが、何故かうまくいきませんでした。
正直ステータスバーの色を変えるだけでこんなに苦労するとは思いませんでした。
「コードを数行ちょちょいと変えるだけでしょ」と甘くみていた数時間前の自分を殴りたいですね。
妥協して白色のステータスバーのままにしようかとも思ったのですが、諦め切れませんでした。

そして行き着いた答えは、

力技でなんとかなるんじゃね?

というスマートさの欠片もない発想でした。

3. SafeAreaを無視してステータスバーと同サイズColorビューを配置

書籍を読んでいた際に、SafeAreaという仕組みがあることを知りました。
SafeAreaとは、ビューを安全に画面に配置するための仕組みで、ステータスバーやナビゲーションなどのUIと干渉しないように設けられている領域らしいです。
デフォルト状態では、このSafeArea内にビューが配置されるようです。


書籍によると、edgesIgnoringSafeAreaモディファイアを使用することでSafeAreaの領域を無視(というか拡張するイメージ?)することができるとのこと。

edgesIgnoringSafeAreaモディファイア
引数にエッジセットを指定すると、そのエッジ方向にSafeAreaを拡張する。
・top -> 上方向に拡張
・bottom -> 下方向に拡張
・horizontal -> 水平方向に拡張
・vertical -> 垂直方向に拡張

そこで、SafeAreaを画面上部まで広げ、ステータスバーと同位置、同サイズのColorビューを配置するという作戦を考えました。

さっそくやってみることに。
修正対象はContentView.swiftファイルです。
まずはVStackを使用し、Colorビュー(ステータスバー役)、Tabビューを垂直方向に並べます。
VStackには、モディファイアとしてedgesIgnoringSafeArea(.top)を追加します。
これにより、画面上部いっぱいにビューが配置できるようになる想定です。

<イメージ>

VStack{
  Colorビュー
  Tabビュー
}.edgesIgnoringSafeArea(.top)

次に、Colorビューのサイズを実際のステータスバーと同サイズにする必要があるため、ステータスバーの高さ情報がほしいところ。こちらに関しては前回記事で記載したGeometryReaderを使用しSafeAreaの上側の領域の高さを取得します。

<イメージ>

GeometryReader{ XXXX in
  VStack{
    Colorビュー.frame(height: XXXX.safeAreaInsets.top)
    Tabビュー
  }.edgesIgnoringSafeArea(.top)
}

気になる実行結果がこちら

おお、それっぽくできたぞ!!

ColorビューとTabビューの間のスペースが気になるので、サイズ調整します。

<イメージ>

GeometryReader{ XXXX in
  VStack(spacing:1){
    Colorビュー.frame(height: XXXX.safeAreaInsets.top)
    Tabビュー
  }.edgesIgnoringSafeArea(.top)
}

実行してみます。

できた!!

ちなみにこの方法ならステータスバーの部分をColorビューで実現するため、ステータスバーを任意の色合いに調整することが可能です。

まとめ

ステータスバーの色を変更するだけなのですが、非常に苦労しました。
色を変更する手順は以下の通りでした。

  1. PJ設定にて、Status Bar Styleの文字色を変更
  2. PJ設定にてStatus Bar Styleの設定を全ての画面に適用するよう設定
  3. SafeAreaを上方向に拡張して、ステータスバーと同サイズColorビューを配置

想定外のところで躓いてしまいましたが..
大小問わずこういった課題を解決したときの喜びはやはり良いものですね。
開発の醍醐味といったところでしょうか。

それではまた次回の記事でお会いしましょう!
最後に今回修正したソースコードを貼っておきます。

//
//  ContentView.swift
//  SmartCurtain
//
//  Created by yagi seijin on 2020/08/14.
//  Copyright © 2020 Loose Life Hack. All rights reserved.
//

import SwiftUI

struct ContentView: View {
    init(){
        UITabBar.appearance().barTintColor = UIColor(named: "tab")
    }
    @State private var selection = 0
 
    var body: some View {
        GeometryReader{ geometry in
            VStack(spacing: 1){
                //ステータスバーと同位置・同サイズのColorビューを配置
                Color.black
                    .frame(height: geometry.safeAreaInsets.top)
                
                TabView(selection: self.$selection){
                    //カーテン制御機能View
                    ControlView()
                        .font(.title)
                        .tabItem {
                            VStack {
                                Image(systemName: "gear")
                                Text("Control")
                            }
                    }.tag(0)
                    //カーテン開閉時刻設定View
                    AlarmView()
                        .font(.title)
                        .tabItem {
                            VStack {
                                Image(systemName: "alarm.fill")
                                Text("Alarm")
                            }
                    }.tag(1)
                    //デバイス接続状態(BLE)View
                    BleStateView()
                        .font(.title)
                        .tabItem {
                            VStack {
                                Image(systemName: "antenna.radiowaves.left.and.right")
                                Text("Search")
                            }
                    }.tag(2)
                }
            }} .edgesIgnoringSafeArea(.top)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

					

コメント

タイトルとURLをコピーしました