質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

5366閲覧

self.viewにおいてsafeArea部分の背景色を透明にして画面上部の時刻を表示させたい

Naoki_Pro

総合スコア23

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/02/09 14:21

編集2020/02/09 14:33

前提・実現したいこと

storyboardなしで開発をしています。
UIViewの上にMKMapViewをaddSubViewしています。

UIViewのsafeArea部分の背景色を自由に変えたいのですが、上手くいきません。
背景色を白やオレンジなどにするとsafeArea部分の時刻などが表示されますが、黒や透明にすると真っ黒になってしまい時刻が表示されなくなってしまうので、この問題を解決したいです。

storyboardなしでの開発が初めてなので理解していないことが多いと思いますが、ご回答よろしくお願いします。

シュミレータ画面

背景色が透明の時

シュミレータ画面

背景色がオレンジの時
シュミレータ画面

下記のコードのコメントアウトを外した時(背景色オレンジ)
シュミレータ画面

該当のソースコード

ViewController.swift

import UIKit import MapKit import CoreLocation class ViewController: UIViewController, MKMapViewDelegate { /* safaAreaの値を取得 */ var safaAreaHeight:CGFloat = 0 var safeAreaWidth:CGFloat = 0 var topPadding:CGFloat = 0 var buttomPadding:CGFloat = 0 var leftPadding:CGFloat = 0 var rightPadding:CGFloat = 0 /* viewの幅と高さを取得するための変数 */ var screenWidth:CGFloat = 0 var screenHeight:CGFloat = 0 /* 位置情報を管理するための変数 */ var locationManeger:CLLocationManager! var mapView: MKMapView = MKMapView() override func loadView() { // print(self.view as Any) super.loadView() print("loadView!!") // print(self.view as Any) print(self.view.backgroundColor as Any) view.backgroundColor = .clear settingLocationManeger() print("背景色:(self.view.backgroundColor as Any)") } override func viewDidLoad() { // print(self.view as Any) super.viewDidLoad() print("viewDidLoad!!") // print(self.view as Any) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) } override func viewWillLayoutSubviews() { // super.viewWillLayoutSubviews() screenWidth = view.frame.size.width screenHeight = view.frame.size.height let safeArea = self.view.safeAreaInsets topPadding = safeArea.top buttomPadding = safeArea.bottom leftPadding = safeArea.left rightPadding = safeArea.right if screenWidth > screenHeight { safaAreaHeight = screenHeight safeAreaWidth = screenWidth - leftPadding - rightPadding         ↓このコメントアウトを外してもレイアウトがズレます。(上に寄る) // self.view.frame = CGRect(x: leftPadding, y: topPadding, width: safeAreaWidth, height: safaAreaHeight) mapView.frame = CGRect(x: leftPadding, y: topPadding, width: safeAreaWidth, height: safaAreaHeight) } else { safaAreaHeight = screenHeight - topPadding - buttomPadding safeAreaWidth = screenWidth - leftPadding - rightPadding print("topPaddingだよ:(topPadding as Any)") print("view.frameだよ:(self.view.frame)") ↓このコメントアウトを外してもレイアウトがズレます。(上に寄る) // self.view.frame = CGRect(x: leftPadding, y: topPadding, width: safeAreaWidth, height: safaAreaHeight) mapView.frame = CGRect(x: leftPadding, y: topPadding, width: safeAreaWidth, height: safaAreaHeight) print("mapView.frameだよ:(mapView.frame)") } // view.backgroundColor = .clear view.addSubview(mapView) // print(self.view.frame) // print(self.mapView.frame) // print(self.view.backgroundColor as Any) } } extension ViewController: CLLocationManagerDelegate { /* 位置情報を取得・更新するたびに呼ばれる */ func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let location = locations.first let latitude = location?.coordinate.latitude ?? 0 let longitude = location?.coordinate.longitude ?? 0 let locationOfCoordinate = CLLocationCoordinate2DMake(latitude, longitude) /* mapViewの中心をユーザーがいる場所に設定 */ mapView.setCenter(locationOfCoordinate, animated: true) var region: MKCoordinateRegion = mapView.region region.center = locationOfCoordinate region.span.latitudeDelta = 0.001 region.span.longitudeDelta = 0.001 /* ピンを生成 */ let pointAnnotation:MKPointAnnotation = MKPointAnnotation() pointAnnotation.coordinate = locationOfCoordinate pointAnnotation.title = "現在地" mapView.addAnnotation(pointAnnotation) mapView.setRegion(region, animated: true) mapView.mapType = MKMapType.standard /* 位置情報の取得を止める */ locationManeger.stopUpdatingLocation() } /* 位置情報の取得に失敗した時に呼ばれる */ func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print(error.localizedDescription) } } extension ViewController { func settingLocationManeger() { locationManeger = CLLocationManager() guard locationManeger != nil else { return } locationManeger.requestAlwaysAuthorization() let status = CLLocationManager.authorizationStatus() switch status { case .restricted, .denied: break case .authorizedWhenInUse, .authorizedAlways: locationManeger.delegate = self locationManeger.distanceFilter = 1 locationManeger.startUpdatingLocation() case .notDetermined: locationManeger.requestAlwaysAuthorization() locationManeger.delegate = self locationManeger.startUpdatingLocation() default: break } } }

ログ画面

背景色が透明の時
ログ画面

背景色がオレンジの時
ログ画面

コメントアウトを外した時(なぜか2回実行されます)
ログ画面

仮説

ログ画面を見る限り、背景色は透明の時もしっかり反映されているように見えます。
もしかしたら背景色の問題ではなく、view.frameのy値を本来44.0とheigthを734.0にしたいのに、0.0と812.0になっていてレイアウトがずれていることが原因な気がするのですが、頭が混乱してます。

試したこと

画面が作られる順番を理解していないのが原因かと思い、画面がどのタイミングで作られるのかライフサイクルの記事を見ながら、func loadView()やfunc viewDidAppee()などを試しましたがわかりませんでした。

safeAreaの取得方法も調べました。

参考にした記事

ライフサイクル
safeAreaの取得方法

補足情報

xcodeバージョン 11.3.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thyda.eiqau

2020/02/09 15:51

背景が黒になっていて時計などの文字色も黒いから重なって見えないだけで、期待通りに動いているように思えますが、何に困っているのでしょうか?
Naoki_Pro

2020/02/10 00:40

お返事ありがとうございます。何に困っているのかの説明が分かりにくかったですm(__)m こちらの説明を追加したら伝わるでしょうか?↓ self.view.backgroundColorを.clearに指定したら、画面上部のsafaArea部分にあるステータスバー(時刻表示など)の黒い文字だけが見えるようになるのではないかと思っていたらsafaArea全体が黒になってしまったので疑問に思っていました。 .blackとした場合は黒背景に黒字なので、真っ黒になるのは理解できるのですが、.clearとした時にも黒背景に黒字になってしまう理由を知りたかったです。
guest

回答1

0

ベストアンサー

ステータスバーの部分が見えなくなる、というのと上に寄ってしまう、という問題が混じっていると思いますが、それぞれ原因があります。

ステータスバーに関しては、単純に黒背景に黒字なので見えていないだけです。
iOS側から見ればステータスバーの背景がどんな色かはわからないので教えてあげる必要があります。
preferredStatusBarStyleをオーバーライドすることで、背景が暗いか明るいかOSに伝えることができます。

上に寄ってしまう問題に関しては、まずviewWill/DidLayoutSubviewsではself.viewのframeやboundsを変えてはいけません。self.viewのレイアウトが完了したからこの関数が呼ばれるので、その中でさらにself.view.frameを変更するとさらに再レイアウトが引き起こされるため2回呼ばれてしまいます。
この関数でしていいのは、基本的にself.viewのsubViewに対してのbounds/frameの変更のみです。

ドキュメントにもありますが、safeAreaInsetsはself.viewが親ビューを覆っていない時は0になります。先のviewWillLayoutSubViewsで2回レイアウトが呼ばれて、2回目は親ビューの矩形よりも内側に寄っているのでsafeAreaInsetsは0になるため、上に寄ってしまいます。

通常、アプリのルートとなるviewのframeは全画面なのでいじる必要がありません。
どのような結果にしたいのかわかりませんでしたが、ステータスバーの部分だけオレンジにしたいなら、空のUIViewを1つ置いて、self.Viewの上からステータスバーの高さの分だけ配置するのがいいと思います。

投稿2020/02/09 16:19

toki_td

総合スコア2850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Naoki_Pro

2020/02/10 00:37

ご丁寧に答えて頂きありがとうございます。 どのような結果にしたいのか、読み返して見たら分かりにくかったですm(__)m 理想の画面レイアウトは完成していてシュミレータの1,2枚目の画像です。 ただ、self.view.backgroundColorを.clearに指定したら、画面上部のsafaArea部分にあるステータスバー(時刻表示など)の黒い文字だけが見えるようになるのではないかと思っていたらsafaArea全体が黒になってしまったので疑問に思っていました。 .blackとした場合は黒背景に黒字なので、真っ黒になるのは理解できるのですが、.clearとした時にも黒背景に黒字になってしまう理由を知りたかったです。 画面のレイアウトが上に寄ってしまうのは確かにまた別の問題でした。ですが非常に分かりやすい説明で理解しやすかったです。
toki_td

2020/02/10 15:33

あぁ、そういうことですか。 self.view.backgroundColorが.clearで、このUIViewContollerが他のUIViewControllerの子でない(self.viewがその他のビューの子でない)のなら、親はUIWindowで、その背景色もデフォルトはclearです。(iOS13以降変なViewが挟まってますがこれもclearです) ですので、上下の部分はアプリが表示しているビュー全ての背景色がclearになっています。 そうすると、完全な透明の背景色はどうなるのか?という話になるのですが、iOSではアクティブなアプリが全画面を覆っているのが前提なのでデスクトップにあたるものがありません。 そのため、iOSとしての背景が見えることは通常ないので、0、すなわち黒で塗りつぶされるので、アプリのすべてのビューの背景色がclearならiOSのデフォルトの背景 = 真っ黒になります。 UIWindowの背景色を設定すればその色になると思いますが、アプリ起動時に作るUIWindowのrootViewControllerであるUIViewControllerのviewは全画面であるべきです。 そこはiOSアプリの前提なので無理に変えないほうがいいでしょう。 ちなみに、Homeの背景をアプリに描画したいなんて話がたまにありますが、システム上不可能です。Homeはデスクトップではなく別のアプリでiOSとしての真の背景は黒だからです。
Naoki_Pro

2020/02/13 07:37

お返事ありがとうございます。 ベストアンサーにさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問