Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
301
Help us understand the problem. What is going on with this article?
@kinopontas

【Swift】超便利StackViewの実践的使い方!まだAutoLayoutで消耗してるの?

More than 5 years have passed since last update.

まだAutoLayoutで消耗しているの?

AutoLayout...。それは今までエンジニアの寿命を縮めてきたものです。こんな経験ありませんか?

Twitterのようなタイムラインを作ろう!!
以下のようなタイムラインを考えてみます。

スクリーンショット 2016-03-21 18.46.12.png

ツイートには画像があるものと無いものがあります。つまり、異なるレイアウトのセルを2つ用意して、場合分けして表示させる方法が一般的でしょう。どちらのセルにもAutoLayoutを設定しなければなりません。ツイートテキストのラベルの高さを可変になになるように設定したり、大変ですよね。

これだけではありません。タイムラインの仕様変更がありました。
『そうだ!リツイートや、ファボができるようにボタンを配置しよう!』
『...』
『AutoLayout付け直し...?オワタ』

スクリーンショット 2016-03-21 18.53.40.png

このようにAutoLayoutは今まで僕らの寿命を縮めてきました。

救世主StackViewの登場

ここでは、上で出てきたタイムラインをStackViewを使ってレイアウトの設定をしていきます。
StackViewの特徴は以下のようなものです。

  • AutoLayoutの設定が最小限に抑えられる
  • hiddenプロパティに対応
  • 部品を再配置がし易い(編集しやすい)
  • 慣れれば超簡単
  • イライラしない
  • ステキ
  • 好きになっちゃう

実践あるのみ。StackViewを使ってタイムラインを作ってみる

セルのレイアウトはxibファイルを使用して作っていきます。

普通に部品を配置する

まずは必要な部品を適当に配置します。(分かりやすく背景色をつけています)

スクリーンショット 2016-03-21 19.05.53.png

ツイート画像を表示するためのImageViewもここで配置しておきます。

StackViewを使う

StackViewを使用する時のポイントは以下の点です。

  • StackViewは部品を暖かく包み込むように使用する
  • 垂直方向、水平方向に並んでいる部品をそれぞれ包み込む

部品同士を暖かく包み込む

まずは小さなグループを見つけます。nameLabelとtimeLabelは水平方向に並んでいるのでStackViewで包み込んであげます。

スクリーンショット 2016-03-21 19.16.30.png

すると小さなStackViewの中にnameLabelとtimeLabelが包み込まれた状態になります。このStackViewをSmallStackViewと呼びましょう。

次に少し大きなグループを見つけます。
SmallStackView, textLabel, tweetImageViewがそれぞれ垂直方向に並んでいるのでStackViewで包み込んであげます。

スクリーンショット 2016-03-21 19.22.51.png

ここで作成したStackViewをMediumStackViewと呼びましょう。
最後にMediumStackViewとiconImageViewが水平方向に並んでいるので、StackViewで包み込んであげます。

スクリーンショット 2016-03-21 19.25.26.png

ここで作成されたStackViewをLargeStackViewと呼びましょう。

StackViewを設定すると部品が少し変な配置になってしまいますが、今はこのままでOKです。

ViewControllerのソースコード

ViewController.swift

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("TweetCell", forIndexPath: indexPath) as! TweetCell
        let tweet = self.tweets[indexPath.row]
        cell.iconImageView.image = tweet.icon
        cell.nameLabel.text = tweet.name
        cell.timeLabel.text = tweet.time
        cell.tweetLabel.text = tweet.text
        cell.tweetImageView.hidden = true
        if let image = tweet.tweetImage {
            cell.tweetImageView.hidden = false
            cell.tweetImageView.image = image
        }
        return cell
    }


このようにツイート画像がある時と無い時でhiddenプロパティを切り替えます。
hiddenにした部品はStackView内では存在しない事として扱われます。つまり、画像が含まれないツイートはImageViewが存在しないように振る舞ってくれます。
これによってセルを2つ用意する必要が無くなります。便利便利便利。

最低限のAutoLayoutを設定しましょう

LargeStackViewの大きさをセルの大きさと一致させるためにLargeStackViewにAutoLayoutを設定します。

制約は上下左右の余白をゼロとして設定します。
ここまでできたら一旦Runしてシミュレータで確認してみます。

スクリーンショット 2016-03-21 19.31.17.png

見るも無残なモンスターが生まれてしまいました。

部分的にAutoLayoutを設定する

アイコンがとっても大きいのでAutoLayoutを設定しましょう。
アイコンに対してwidthとheightの値を具体的に設定し制約を追加します。

スクリーンショット 2016-03-21 19.32.50.png

ちょっと綺麗になりました。
次にツイート画像の高さが大きすぎるので、ツイート画像のImageViewにもAutoLayoutを設定します。

スクリーンショット 2016-03-21 19.36.16.png

だいぶ良くなってきました。
しかし、名前、時間、テキストのラベルが不格好なので整頓していきましょう。

StackView内の部品の整列させる

MediumStackViewの中の部品をそれぞれ整頓させていきたいです。
そこで、StackViewのAlignmentを設定します。
AlignmentをFillに設定しましょう。

スクリーンショット 2016-03-21 19.39.25.png

めちゃ良い感じになってきました。
しかし、このままですと部品同士がくっついていて窮屈です。そこで余白を設定してみましょう。

部品同士に余白を設定する

余白を設定するためにはStackViewのSpacingを設定します。
以下の画像のようにStackViewにSpacingを設定すると、StackViewに包まれている部品に余白を付けることができます。

スクリーンショット 2016-03-21 19.45.47.png

これで、とってもスッキリして気持よくなりました。
これで終わりでも良いのですが、この状態から新たに部品を配置してみたいと思います。

部品を追加する

ここでは、セルの下部にリプライ、リツイート、ファボの3つのボタンを配置します。

既存のStackViewに新たに部品を配置する。

MediumStackViewはSmallStackView, textLabel, tweetImageViewを垂直方向に配置させているものでした。このMediumStackView内に新たにButtonを配置します。

スクリーンショット 2016-03-21 19.55.43.png

次に、配置したButtonから水平方向に続くようにもう2つButtonを配置したい所です。
2つ目のButtonを配置する前に1つ目のButtonをStackViewで包んであげます。
この時StackViewのAxis属性をHorizontalに設定しましょう。ボタンを水平方向に配置していきたいからです。

スクリーンショット 2016-03-21 20.01.46.png

ここで作成したStackViewの中に残り2つのボタンを配置します。

スクリーンショット 2016-03-21 20.04.30.png

上の画像のようにDistributionをFill Equallyに設定します。すると3つの部品のWidthが均等になるように配置してくれます。超便利です。

完成です。

スクリーンショット 2016-03-21 20.51.04.png

ちなみに、画面を横に回転させても自動でレイアウトし直してくれます。とっても助かります。

スクリーンショット 2016-03-21 21.42.39.png

最後に

最後にポイントをおさらいです。

  • StackViewは水平方向、垂直方向に並んでいる部品同士を暖かく包み込むように使用する
  • hidden = trueを設定した部品は、その部品が存在しないようにレイアウトされる
  • StackViewの大きさは中の部品の大きさ(テキストの量や画像サイズ)に依存する
  • 特定の部品の大きさを制御したい場合は部分的にAutoLayoutを設定する。
  • SpacingによってStackView内の部品同士の余白を設定する
  • StackViewのアトリビュートインスペクタをイジイジすることで様々なパターンの整列を行うことができる(幅均等など)
  • 画面回転時に自動でレイアウトし直してくれる。

アプリのソースコードはコチラ

301
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
301
Help us understand the problem. What is going on with this article?