前回のつづき。

今回はScrollViewおよびそのSubclassを表示する場合について。

サンプルコード: https://github.com/stack3/iOS7FullScreenViewSamples

前回のサンプルコードを起動して、ScrollView with NavigationBar and Toolbarを選択してください。

TextView(ScrollViewのSubclass)が表示されています。

000

上へスクロールさせてみましょう。

001

StatusBarとNavigationBarに文字が透けてにじんだようになっています。

005

 

Toolbarの方も見てみると同じように文字が透けています。

006

スクリーンショットではわかりづらいかもしれませんが、実際に動かしてみるとわかります。

このようにスクロールの内容がNavigationBarなどに透けて見える動作は、Appleのプリインストールアプリにも見られます。

スクロールした内容を透けてみせるからくり

UIScrollViewにはcontentInsetというプロパティがあります。これはスクロールの内容の上下左右の余白を設定するものです。

contentinset

たとえば、以下のようにcontentInsetを設定したとします。

scrollView.contentInset = 
   UIEdgeInsetsMake(100  /*top*/, 
                    0    /*left*/, 
                    100  /*bottom*/, 
                    0    /*right*/);

すると上へスクロールした時、中身よりさらに100px余分にスクロールできるようになります。つまり100px分の余白ができます。下へスクロールした時は、中身より100px余分にスクロールできるようになります。

先ほどの画面をレイアウトしているSTScrollViewController.storyboardを開きます。

このようにView全体にTextViewを貼り付けています。

007

 

TextViewのConstraintを見てみましょう。TextViewを選択してSize Inspectorで確認できます。

008

このようにTop Space、Bottom SpaceはLayout GuideではなくSuperviewになっています。つまり、StatusBar、NavigationBar、Toolbarと重なって配置されています。にもかかわらず、最初に表示した時、内容がこれらの下に隠れないのは、contentInsetが設定されているからです。

viewWillAppearで以下のようにTextViewのcontentInsetをNSLogで出力しています。

NSLog(@"contentInset:%@", NSStringFromUIEdgeInsets(_textView.contentInset));

出力されたLogは以下のようになります。

contentInset:{64, 0, 44, 0}

topは64pxはStatusBar、NavigationBarの高さの合計です。bottomの44pxはToolbarの高さです。これによりTextViewの内容は上下に余白ができてStatusBar、NavigationBar、Toolbarと重ならないようになっています。

このcontentInsetは、ViewControllerが自動で設定してくれます。iOS 7からUIViewControllerにautomaticallyAdjustsScrollViewInsetsというプロパティが追加されました。YESのとき、ViewControllerが管理するviewに配置されたScrollViewおよびSubclassのcontentInsetを適切な値に設定してくれます。デフォルトでYESになっているので、Storyboard上でScrollViewのConstraintさえ正しく設定しておけば機能します。

自分で配置してみる

TextViewをいったん削除して自分で配置してみましょう。ドラッグ&ドロップするとべたっとView全体に貼り付けられます。

009

このままだとスクロールしないので、文字を適当に増やします。TextViewのAttributes Inspectorを開いて、Textの既存の文字をコピー&ペーストするなどして増やします。

010

 

文字色が黒のままだとNavigationBarなどの後ろに透けているのがわかりづらいので赤にします。

011

 

この段階で起動してもうまくいっているように見えます。(スクロールさせるとNavigationBar、Toolbarに透けている)

012

しかし、これはStoryboard上で4.0インチサイズでViewを作り、かつ、4.0インチのSimulatorや端末で動かしたときだけです。3.5インチではTextViewが画面下へはみ出て最後までスクロールできませんし、横画面にしても幅が伸びません。きちんとConstraintを設定しましょう。

TextViewのConstraintをこのように設定します。

013

 

これで上下左右の間隔が0になったはずです。起動して確認してみましょう。

一見うまくいっているように見えますが、下までスクロールさせると余白ができてしまいました。

014

また、よくみるとToolbarの後ろに文字が透けてないようです。Toolbarの上端だけ若干赤く見えるのは、Toolbarの真上の色が反映されるという別の仕様です。

015

なぜこうなったのでしょう。TextViewのSize InspectorからConstraintsを確認してみます。

017

Bottom Space to: Bottom Layout Guideになっています。つまりTextViewの下端はToolbarの上端になってしまっています。さらにautomaticallyAdjustsScrollViewInsetsの働きでcontentInset#bottomが44pxに設定されているので空白ができるのです。

いったん、Constraintを削除してもう一度設定しなおしましょう。Resolve Auto Layout Issuesボタンを押して、Clear Constraintsを選択します。

018

 

これでTextViewのConstraintが全部消えました。Pinボタンを押してもう一度設定しなおしましょう。

013

 

そして、BottomのConstraintのプルダウンを押します。

019

Bottom Layout Guideにチェックが入っているので、Viewを選択して変更します。

Size InspectorからConstraintが以下のように設定されたことを確認してください。

020

 

起動すると今度はうまくいくはずです。

NavigationBarにToolbar透けて見えて、最後までスクロールさせても余白はできません。

001

022

その3へつづく