↑クリックして拡大
↑クリックして拡大
↑クリックして拡大
↑クリックして拡大

頭痛が減ったので共有です!

rebuild.fmを応援しています!

HOME > AutoLayout

AutoLayout

自動にレイアウトを調整するAutoLayoutですが、どのサンプルを見てもなんともわかりずらいので、図とサンプルを使ってできるかぎり簡単に作成してみます。 なお、プログラムでAutolayoutするサンプルで、StoryBoardでの利用方法とは違いますのでご了承ください。

参考:プログラム(Visual Format Language)によるAuto Layout
参考:NSLayoutConstraintを使ってAutoLayoutをコードで書く
参考:コードでAutolayout

まずやってみます。目標は以下のような形です。1、2、3、4とそれぞれ実装していきます。

レイアウトサンプル

1=ラベル。w100%,h50px
2=ウェブビュー。w100%,h300px
3=ボタンそれぞれw=25%,高さ50px。
を目標にします

やってみる(#1ラベル of 3)1のラベルを画面上部にはりついた状態を

このconstraintsWithVisualFormatがいまいちピンときません。難しい、、、、ひとまず少しずつ進めていきます。


        //テストのUILabel作成
        var label1 = UILabel(frame: CGRectMake(0, 0, 0, 0));
        label1.text = "中年サラリーマンです!";
        self.view.addSubview(label1);
        label1.setTranslatesAutoresizingMaskIntoConstraints(false)//Autolayoutの時はここはfalse
        label1.backgroundColor = UIColor.yellowColor();
        label1.textAlignment = NSTextAlignment.Center
        self.view.addSubview(label1);
        
        //オブジェクトと名前を宣言します。この変数名は任意。ここが勘違いしやすいかも。Objective-CならNSDictionaryOfVariableBindingsのマクロを利用
        let viewsDictionary = ["top_hogehoge":label1];

        //両サイド8ピクセルのpaddingを追加
        let view_constraint_1:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[top_hogehoge]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        
        //上のpaddingを50ピクセル。V:=Vertical。縦方向。H:=Horizontal横方向
        let view_constraint_2:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[top_hogehoge]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        
        //反映
        view.addConstraints(view_constraint_1)
        view.addConstraints(view_constraint_2)
        

autolayoutサンプル画像

ひとまず上記で上のラベルを作成しました。こちら感覚としてはStyleSheetのCSSに似ているのかなと思いました。まず、オブジェクトの名前を決定して、それに個別にCSSを反映させていく形でしょうか。コードは長いですが、キモはconstraintsWithVisualFormatの後ろの記載方法になるのかと思います。

constraintsWithVisualFormatの中の←この縦棒に注意です!これは画面の端を表しますので、この縦棒の有無で表示が変わってしまいます。

やってみる(#2WebView of 3)1のラベルの下に300pxのWebViewを追加する


        //1のラベル
        var label1 = UILabel();
        label1.text = "中年サラリーマンです!";
        self.view.addSubview(label1);
        label1.setTranslatesAutoresizingMaskIntoConstraints(false)
        label1.backgroundColor = UIColor.yellowColor();////背景色
        label1.textAlignment = NSTextAlignment.Center
        self.view.addSubview(label1);
        
        //WebView(以下はWKWebViewを利用しています)
        let webView = WKWebView(frame: CGRectZero, configuration: WKWebViewConfiguration())
        webView.setTranslatesAutoresizingMaskIntoConstraints(false)
        let url = NSURL(string: "http://google.com")
        let request = NSURLRequest(URL: url!)
        webView.loadRequest(request)
        view.addSubview(webView)
        
        //配列にwebviewの要素を追加します。
        let viewsDictionary = ["top_hogehoge":label1,"middle_hogehoge":webView];//NSDictionaryOfVariableBindings Objective-C
        
        //1.label1の両サイドに8ピクセル
        let view_constraint_1:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[top_hogehoge]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        
        //2.画面上から50ピクセル下にlabel1、その下にwebview(高さ300ピクセル)
        let view_constraint_2:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[top_hogehoge]-[middle_hogehoge(300)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
       
        //3.webviewの両サイドに8ピクセル
        let view_constraint_3:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[middle_hogehoge]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        
        view.addConstraints(view_constraint_1)
        view.addConstraints(view_constraint_2)
        view.addConstraints(view_constraint_3)
        

autolayoutサンプル画像

constraintsWithVisualFormatですが、間違った記述をするとTerminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse constraint format: Expected the end of the format string のエラーが変数宣言だけで参照していなくても発生するので注意です。例えば、上記のlet view_constraintの配列の記載が間違っていると、letの宣言をするだけで落ちます。

やってみる(#3ボタン of 3)2のWebViewの下にボタンが4つ横に並ぶ

最後にボタンの追加です。それぞれのボタンコントロールに対してconstraintをセットしていきます。


        var label1 = UILabel();
        label1.text = "中年サラリーマンです!";
        self.view.addSubview(label1);
        label1.setTranslatesAutoresizingMaskIntoConstraints(false)
        label1.backgroundColor = UIColor.yellowColor();////背景色
        label1.textAlignment = NSTextAlignment.Center
        self.view.addSubview(label1);
        
        let webView = WKWebView(frame: CGRectZero, configuration: WKWebViewConfiguration())
        webView.setTranslatesAutoresizingMaskIntoConstraints(false)
        let url = NSURL(string: "http://google.com")
        let request = NSURLRequest(URL: url!)
        webView.loadRequest(request)
        view.addSubview(webView)
        
        //ボタンx4追加
        var button1 = UIButton(frame: CGRectMake(0, 0, 100, 50));
        button1.backgroundColor = UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0);
        button1.setTranslatesAutoresizingMaskIntoConstraints(false)
        button1.setTitle("Test1", forState: UIControlState.Normal);
        self.view.addSubview(button1);
        
        var button2 = UIButton(frame: CGRectMake(0, 0, 100, 50));
        button2.backgroundColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0);
        button2.setTranslatesAutoresizingMaskIntoConstraints(false)
        button2.setTitle("Test2", forState: UIControlState.Normal);
        self.view.addSubview(button2);
        
        var button3 = UIButton(frame: CGRectMake(0, 0, 100, 50));
        button3.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0);
        button3.setTranslatesAutoresizingMaskIntoConstraints(false)
        button3.setTitle("Test3", forState: UIControlState.Normal);
        self.view.addSubview(button3);
        
        var button4 = UIButton(frame: CGRectMake(0, 0, 100, 50));
        button4.backgroundColor = UIColor(red: 0.0, green: 1.0, blue: 1.0, alpha: 1.0);
        button4.setTranslatesAutoresizingMaskIntoConstraints(false)
        button4.setTitle("Test4", forState: UIControlState.Normal);
        self.view.addSubview(button4);
        
        //マトリックス追加。これは変数をvisualFormatに利用したい場合に使います。
        //画面の横幅に応じてボタンのサイズがかわるので、画面サイズからpadding分の数値を引いて4分割。
        let metricsDictionary = ["btnw_hogehoge":(Int( UIScreen.mainScreen().bounds.size.width)-50)/4];
            
        //ボタンを追加
        let viewsDictionary = ["top_hogehoge":label1,"middle_hogehoge":webView,"bottom_btn1_hogehoge":button1,"bottom_btn2_hogehoge":button2,"bottom_btn3_hogehoge":button3,"bottom_btn4_hogehoge":button4];//NSDictionaryOfVariableBindings Objective-C
        
        let view_constraint_1:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[top_hogehoge]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        let view_constraint_2:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[top_hogehoge]-[middle_hogehoge(300)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        let view_constraint_3:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[middle_hogehoge]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)  
        //横並びの設定。btnw_hogehogeの幅でbutton1、button2と並べていく。
        let view_constraint_4:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-8-[bottom_btn1_hogehoge(btnw_hogehoge)]-8-[bottom_btn2_hogehoge(btnw_hogehoge)]-8-[bottom_btn3_hogehoge(btnw_hogehoge)]-8-[bottom_btn4_hogehoge(btnw_hogehoge)]", options: NSLayoutFormatOptions(0), metrics: metricsDictionary, views: viewsDictionary)
        //以下はそれぞれのボタンの縦並びの設定をひとつずつ設定する。
        let view_constraint_5:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[middle_hogehoge]-[bottom_btn1_hogehoge(50)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        let view_constraint_6:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[middle_hogehoge]-[bottom_btn2_hogehoge(50)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        let view_constraint_7:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[middle_hogehoge]-[bottom_btn3_hogehoge(50)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        let view_constraint_8:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:[middle_hogehoge]-[bottom_btn4_hogehoge(50)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
        
        view.addConstraints(view_constraint_1)
        view.addConstraints(view_constraint_2)
        view.addConstraints(view_constraint_3)
        view.addConstraints(view_constraint_4)
        view.addConstraints(view_constraint_5)
        view.addConstraints(view_constraint_6)
        view.addConstraints(view_constraint_7)
        view.addConstraints(view_constraint_8)
        

autolayoutサンプル画像

今回はひとつひとつのコントロールにそれぞれconstraintsを設置しましたが、ボタンの箇所なんかはviewに全て追加してからviewに対して constraintsを追加する等の事を実行した方がスッキリしそうです。

autolayoutの理解、、、、正直とっつきずらかったですが、上記サンプルコードで少しでもなるほどとなっていただければ感謝です。使いづらい等のコメントも多くネット上に記載されていましたが、今後のiPhoneの サイズ多様化が進むにつれて必要になってきそうなautolayoutでした。

↓こんな記事もありますよ!


2021-05-14 14:21:41

WatchOSのwatchconnectivityのFiletransferの落とし穴。と、避け方。

AppleWatch 実機だと成功するんだけど、シュミレーターだと失敗するという、、、 昔作成してた時は成功してたのになーと思って調べると、どうやら昔は成功してたみたい。watchOS6以降は...

2021-05-06 14:04:37

LINEのアニメーションスタンプ制作の落とし穴、、、失敗談

ゴールデンウィークにLINEスタンプを作成してみました。 作り切って申請も通したんですが、意図したアニメーションと違う、、、、 LINEクリエーターの画面だと、アニメーションのプレビュー...

2021-05-01 18:05:35

久しぶりのAdmobをobjective-cに実装。コンパイルエラーだらけ。バーミッション不具合でエミュレータにインスコできない。

忘れないようにメモ エミュレータにアプリをインストールする際にパーミッション系のエラーがでた時、また、iphone実機にインストールする際にも権限系のエラーが出る場合。 ターゲット→ex...
このエントリーをはてなブックマークに追加
右側のFacebookのLikeをクリック頂けると記事更新の際に通知されますので宜しければご利用下さい!