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

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

ただいまの
回答率

90.61%

  • Objective-C

    1172questions

    Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。

<Objective-c>viewControllerのview領域がnavigationBarよりも上に設定できない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,624

deltaZone

score 3

objective-cのステータスバー及びナビゲーションバーについて質問させてください。

▶︎navigationBarとstatusBarを透過にして任意の画像を共通の背景に設定する、
もしくは
▶︎statusBarの領域にnavigationBarの背景を共有する、
のいずれかが実現したいのですが
navigationControllerによって管理されているviewController上に
スクロールビューやCollectionViewを使ってviewを作ると

イメージ説明
のような状態になり、statusBar領域には最背面のwindowの色が反映され、
navigationBarと分離された状態になってしまいます。さらにviewControllerのビュー領域がnavigationBarより上に潜り込みません。

該当のviewControllerのviewDidLoad内では

    self.automaticallyAdjustsScrollViewInsets = NO;
    [self setEdgesForExtendedLayout:UIRectEdgeNone];

を設定し、
storyBoardでは
    adjust scroll view insets のチェックを外す
    under top barのチェックを入れる
という設定を試しましたが、うまくいきません。

EdgesForExtendedLayoutやcontentInsetsの基本的なことも
覚束ないので、指南していただければ助かります。

補足:
NavigationControllerは

    [[UINavigationBar appearance] setBackgroundImage:[UIImage new] 
    forBarPosition:UIBarPositionTopAttached barMetrics:UIBarMetricsD
    efault];
    [[UINavigationBar appearance] setFrame:CGRectMake(0,0,[UIScreen
    mainScreen].bounds.size.width, 64)];
    [[UINavigationBar appearance] setShadowImage:[UIImage new]];
    [[UINavigationBar appearance] setTranslucent:YES];
    [[UINavigationBar appearance] setBackgroundColor:[UIColor 
    clearColor]];
のように透過させています。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Stripe

    2015/09/04 01:11

    ところで、なぜnavigationBarをstatusBarの領域に表示させたいんですか?通常であれば、むしろ困ると思うんですけど?

    キャンセル

  • deltaZone

    2015/09/04 01:56

    現在は追加した画像のように背景が分かれているんですが、 各ボタンやラベルを残して、背景に統一感を出したいと考えています。 一言で言えばデザインの観点からです。

    キャンセル

回答 1

checkベストアンサー

0

ステータスバーの背景色はもともと透明ですが、ナビゲーションバーの背景はデフォルトで曇りガラス状になっているのをどうやって透明にしているんですか?
もし、ナビゲーションバーの背景画像に透明の画像を貼り付けることでコンテンツを透過させているんだったら、その画像の縦サイズを確認してみてください。もし縦サイズが44ピクセル(@2xで88ピクセル)なら、質問にあるようにステータスバーの部分に背景画像が適用されず、黒く表示される現象が発生します。ナビゲーションバーに背景画像を貼る場合、ステータスバーの部分も含めた縦64ピクセル(@2xで128ピクセル)の画像が必要です。

以下のURLで最高得票を得られた回答の4,5あたりをよく読んでみてください。
http://stackoverflow.com/questions/18294872/ios-7-status-bar-back-to-ios-6-default-style-in-iphone-app

もし透明画像を使わずにナビゲーションバーを透明にしているのでしたら、どうやって透明にしているか補足ください。

Adjust Scroll View InsetsやExtended Edgesについては、
まずviewDidLoad内で設定した
   self.automaticallyAdjustsScrollViewInsets = NO; 
   [self setEdgesForExtendedLayout:UIRectEdgeNone]; 

storyBoardで設定した
   adjust scroll view insets のチェックを外す 
   under top barのチェックを入れる 
は、同じものを設定しており、両方で設定した場合はまずstoryBoardから
読み込んだ値を適用してロードし、その後すぐviewDidLoadの設定で
上書きされると認識してください。

その上で以下のURLの解説を読んでみることをお勧めします。
http://qiita.com/yimajo/items/254c7cebab7864678246

今回の場合、ナビゲーションバーにViewControllerのビューを潜り込ませたいのですから
edgesForExtendedLayoutはUIRectEdgeTopの指定が必須です。

automaticallyAdjustsScrollViewInsetsについては、
スクロールアップした時にコンテンツの開始位置がナビゲーションバーと
重ならないようにしたければYESにすればいいし、
画面の一番上(ステータスバーと重なる部分)がコンテンツの開始位置
となるようにしたければNOを設定すればいいです。
複雑な画面ならAutoAdjustに頼るのではなく、自分で意図するレイアウトになるよう
scrollViewInsetsを自分で調整した方がよいかもしれません。


(9/10追記)
透明にする方法について補足と疑問点についてコメントを頂いたので追記します。

まず、透明にする方法についてですが
[[UINavigationBar appearance] setBackgroundImage:[UIImage new] forBarPosition:UIBarPositionTopAttached barMetrics:UIBarMetricsDefault]; 

setBackgroundImageで[UIImage new]を指定しているということは、0x0サイズの画像を
背景画像として貼り付けているということです。
私は0x0サイズの画像をナビゲーションバーに貼り付けたことはなかったので、どうなるか確認してみた
ところ、ステータスバーの部分は黒くならず、一番下に重なっているスクロールビューのコンテンツが
表示されました。つまり私のテスト環境では意図通り動作しました。
ただ、0x0サイズの画像というのはとても特殊なので、環境によって変わる不定動作を引き起こすのかもしれません。
念のため縦64ピクセルの透明画像を貼り付けて試してみた方がよいように思います。
縦64ピクセルの透明画像を貼り付けるには、
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(320, 64), NO, 0);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
で、imageを作成し、[UIImage new]の替わりにimageを指定すればよいです。

次にコメントに書かれている疑問点についてですが、
まず、「scrollViewInsets」と書いているのは「UIScrollViewクラスのcontentInset」の誤りです。うろおぼえのままちゃんと確認せず書いてしまいました。すみません。contentInset.topを指定するという認識で正しいです。
ただ、今回の問題(ステータスバーの部分が黒くなる)は、contentInsetの設定とは関係ないと思います。まずはステータスバーの部分が黒くなる問題を解消してから、contentInset.top(スクロールエリアの余白)は後で調整したのでよいと思います。


投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/10 15:31

    本文に透過についての補足をしました。
    UIRectEdgeTopを設定しましたが解消できません。
    scrollViewInsetsの設定はどのようにやるのでしょう?
    おかしい所がスクロールビューまたはそのサブクラスを使っている所だけで、
    教えていただいたqiitaのurl等からもcontentInsets.topの設定かなと想像しているのですが、scrollViewInsetsの設定するということはcontentInsets.topを設定するということと同じなんでしょうか。これらの設定方法が分かりません。。

    キャンセル

  • 2015/09/10 17:09

    頂いた補足に対応して回答を追記しましたので確認ください。

    キャンセル

  • 2015/09/10 19:59 編集

    大変わかりやすくて助かります。
    言われた方法を試しましたが、結果が変わりません。
    度々コメントにて質問してしまい申し訳有りませんが、
    appDelegate内のdidFinishLaunchingWithOptionsで
    self.windowの背景色を変えたところ、ステータスバーがwindowの背景色と同じになる事が新しくわかったのですが、これはunderTopBar(UIRectEdgeTop)がステータスバーに対してきいてない、ということなのでしょうか?

    キャンセル

  • 2015/09/11 00:41

    ステータスバーがwindowの背景色と同じになるということなら、私が指摘した透明画像の縦サイズの問題とは別件になります。縦サイズを44ピクセルにした時は、ステータスバー部分の残り20ピクセルは(windowsの背景色でなく)常に黒になります。
    おそらくなんらかの原因でViewControllerのビューが20ピクセル下から表示されているのではないかという気がしますが、どのようにしたらそういう状況になるのか推測するのは難しいです。例えばUINavigationControllerの設定でナビゲーションバーの表示をOFFにし、別途自分でナビゲーションバーを貼り付けたりしていませんよね?

    とりあえず、「Master-Detail Application」テンプレートを使った新規プロジェクトを作成し、それにあなたが提示した透明化コードをAppDelegate内のdidFinishLaunchingWithOptionsに加えるだけで、ちゃんとステータスバーもナビゲーションバーも透明になって、下に重なったスクロールビューが透過表示されるアプリが作れるはずです。それを自分で作って確認した上で、自分のプロジェクトとどう違うか差異を分析すれば何か原因がわかるかもしれません。

    キャンセル

  • 2015/10/17 19:11

    takeOneさんの回答からrecursiveDescriptionでviewControllerの階層構造を調べたところ、
    確かにViewControllerのビューが20ピクセル下から表示されている、とわかったので
    さらに調べたところ 一定の条件を満たしたUIViewControllerのスクロールビューに対して、自動的にcontentInsetsが付与されることがわかりました。
    (http://qiita.com/glayash/items/b759bd1da0aedf8adc82)
    このinsetsはsubViewsにも影響するものらしく
    それまでストーリーボード間で同じnavigationControllerを使っていたので、
    ストーリーボード毎に新しいnavigationControllerを用意し、その中で明示的にframeの座標に(0,0)を指定をしたところ、それ以降のviewControllerが(0,0)座標に表示できて
    任意のviewImageをつかってstatusBar/navigationBarの背景にすることができました。
    どうもありがとうございました。

    キャンセル

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Objective-C

    1172questions

    Objective-Cはオブジェクト指向型のプログラミング言語のひとつです。C言語をベースにSmalltalkが取り入れられています。