リブートキャンプ by Swift 目次

 

 前にUIViewが画面を管理するって言ったっけ?

 すまん、ありゃ嘘だ。

 まあ、嘘じゃないにしろ正確じゃない。

 正確には、画面表示に関してはUIViewオブジェクトが所有するCALayerオブジェクトが受け持ってます。

 それが、前回出てきたUIViewのlayerプロパティに設定されているオブジェクト。

 UIViewはいわば総合商社(ゼネコン)みたいなもんすね。

 発注を受けて下請けに丸投げしたりします。

 

 

 例えば、以前説明した、背景色の指定であるUIViewのbackgroundColorプロパティへのUIColor設定は、UIView内部で、このCALayerのbackgroundColorプロパティを設定してたりします。

 

 

 こんなまだるっこしい構成にしてるのは、一つは機能の分業化です。

 CALayerは画面表示に専念し、ユーザーからの画面タップには無関心。そっちはUIViewが担当することになってます。

 これが分業。

 もう一つはMac、iPhone開発時の共通機能の共有のため。

 画面表示機能はMacでもiPhoneでも考え方・扱い方は同じ(RGBで色を指定とか)なので、この機能を同じCALayerというクラスで提供してもらえると、アプリを作るプログラマは、1つのクラスを知ることでMacでもiPhoneでも画面表示プログラムを書けるようになる。

 覚えることが減って助かるんですよ。

 ただし、画面タップ、マウスクリックという機能はiPhone、Macで異なる部分なんで、そこは、それぞれのプラットフォーム(iPhone、Mac)別々のクラスを用意する。それがUIViewというわけです。ちなみにMacアプリで画面管理するオブジェクトはNSViewと言います。

 

 

 内部で複数のオブジェクトを構成して分業してるけど、外部とのやりとりは基本的に1つの元締めオブジェクト(UIView・NSView)が対応する。

 コンポーネントというプログラミング手法です。

 ま、そんなわけで実際の画面表示はCALayerが請け負ってるので、直接CALayerにナシをつけた方が細かな指示ができたりもするんですよ。

 UIView側に依頼窓口が用意されてないやつとかもある。

 それがlayerプロパティのconerRadiusやmasksToBoundsといったプロパティの設定。

    override func viewDidLoad() {
		・・・
        let back = UIVisualEffectView(frame:frame.insetBy(dx: 20, dy: 20))
        back.layer.cornerRadius = 16
        back.layer.masksToBounds = true
		・・・

 conerRadiusの方は矩形の四隅に丸みをつける指定です。角の丸みを半径で指定する。

 

 

 他に枠線の幅を指定(borderWidth)して枠線を表示したり、枠線の色(borderColor)を指定したりもできる。

 

サンプル:

http://tetera.jp/xcc/book-sample/layer.zip

 

        let sampleView = UIView(frame: CGRect(x: 100, ・・・
        self.view.addSubview(sampleView)
        sampleView.layer.borderWidth = 1
        sampleView.layer.cornerRadius = 8
        sampleView.layer.borderColor = UIColor(
            hue: 0.6, saturation: 0.2, brightness: 1, alpha: 1).cgColor
//        sampleView.layer.shadowOpacity = 0.5
//        sampleView.backgroundColor = .white

 

 

 borderColorプロパティに設定してるのが、UIColorじゃなくCGColorだってことにも注意が必要っす。ここら辺は以前教えたクイックヘルプで調べましょう。

 とにかくCALayerの色関係にはUIColorは指定できない。CGColorを直接作るのは手間なんで、一旦UIColorを作って、そのプロパティからCGColorを取り出して指定します。

 こんな感じで、変数や定数に入れなくても、オブジェクト作成のUIColor(hue:…)の後ろに .(ドット)とプロパティ名とすることで、作ったUIColorオブジェクトにアクセスできます。

 

 

 作ったUIColorオブジェクトは、変数や定数に入れてないんで、これ以後は使えなくなるだけど、CGColorを取り出したら用済みなんで問題ない。

 それと今回はRGBじゃなくHSB指定でUIColorを作ってます。hueが色相(0.0〜1.0 0.0が赤で0.33..で緑、0.66...で青と変わり1.0で赤に戻る)。

 

 saturationが彩度(0.0〜1.0 1.0で一番鮮やか), brightnessが明度(0.0〜1.0 1.0で一番明るい)。

 

 枠線の他に、shadowOpacityプロパティの値を、0以外にすると影が表示されたりもします。

 

 

 サンプルでコメントにしている

 

   // sampleView.layer.shadowOpacity = 0.5

 

の // 部分を消して有効にして試すといいでしょう。その後で、その次の行のコメント部

 

   // sampleView.backgroundColor = .white

 

を有効にして試すとこんな感じになります。違いがわかるかな?

 

 

 CALayerにどんな指定ができるか、詳しくはこの前教えたクイックヘルプを使って調べてみてください。

 

 それと、この角丸矩形にしてるUIVisualEffectViewは、画面にすりガラス効果を持たせるUIView派生オブジェクトです。

 effectプロパティにUIBlurEffectを指定することですりガラス効果を指定できる。

        let back = UIVisualEffectView(
                frame:frame.insetBy(dx: 20, dy: 20))
                ・・・
        back.effect = UIBlurEffect(style: UIBlurEffectStyle.light)

 自分の後ろにある画像を、すりガラス加工するので、後ろがただの白地だと効果はありません。

 

 

 で、このすりガラス処理した画像は矩形で表示されるので、このままだと角丸矩形にならないんですよ。そのために

        let back = UIVisualEffectView(
                frame:frame.insetBy(dx: 20, dy: 20))
        back.layer.cornerRadius = 16
        back.layer.masksToBounds = true
        back.effect = UIBlurEffect(style: UIBlurEffectStyle.light)

として、画像が角丸矩形をはみ出さないようにしてます。

UIView側で指定するなら

 

        back.clipToBounds = true

 

とします。どっちで指定してもいいです。

 その後のセリフ部分(文字)のUILabelに対する

        //  セリフ部分(文字)
        let message = UILabel(frame:frame.insetBy(dx: 30, dy: 30))
        message.font = UIFont.preferredFont(
                forTextStyle:UIFontTextStyle.title1)

はダイナミックタイプ用文字の指定。

 設定アプリの「画面表示と明るさ」項目にある「文字サイズを変更」で、文字の大きさを変更すると、それに合わせて文字の大きさが変わるようになります。

 

 

 ただし、ちゃんと対応してないので、起動した時だけです。

 なのでダイナミックタイプフル対応とは言えない。

 ここら辺の話は次回!