UILabelでタグっぽい見た目を実装する

`UILabel`を利用して、↓の写真のようなタグっぽい見た目のviewを実装する。
![スクリーンショット 2015-12-02 23.48.13.png](https://qiita-image-store.s3.amazonaws.com/0/1795/9ad7c33d-fcc7-f8a7-94bb-15e38254c938.png)
ざっくり言ってしまえば`UILabel`にボーダーつけて終わり、なんですがｗ

## まずは1個のタグ

StoryBoardに`UIViewController`をおいて、`ViewController.swift`に表示内容を書いていく。
まずはタグ表示に利用する`UILabel`の子クラスを作成。

`init`でタグのボーダーや角丸の設定などを行ってしまっている。
プロパティの`tagPadding`は、タグ内の文字のパディング幅。

`drawRect(_:)`をオーバーライドし、`UIEdgeInsets`で上下左右に`tagPadding`分のinsetをつけて`drawTextInRect(_:)`で`return`している。

```swift:ViewController.swift
import UIKit

class TagLabel: UILabel {
    
    let tagPadding: CGFloat = 5
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        layer.cornerRadius = 2
        layer.borderColor = UIColor.blackColor().CGColor
        layer.borderWidth = 1
        textColor = UIColor.blackColor()
        clipsToBounds = true
        numberOfLines = 1
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func drawRect(rect: CGRect) {
        let insets = UIEdgeInsets(top: tagPadding, left: tagPadding, bottom: tagPadding, right: tagPadding)
        return super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))
    }
    
}
```

続いて、`ViewController`クラスの実装。

`tagLabelTextWidth(text:font:height:)`メソッドでタグの幅を計算する。
中でやっていることは単純。

* 一度ダミーのインスタンス（`UILabel`）を生成
* `sizeToFit()`してラベル幅を中のテキストぴったりに合わせ、タグの文字となる部分のwidthを算出
* 上記の値に、左右のパディング幅を加えた値を返す

ということを行っている。
その後、`viewDidLoad()`内で、算出したタグの幅を利用して本物の`TagLabel`を作り`addSubview`。

```swift:ViewController.swift
class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let tagFont = UIFont.systemFontOfSize(16)
        let tagHeight = tagFont.lineHeight + TagLabel().tagPadding * 2
        let tagText = "hoge"
        let tagWidth = tagLabelTextWidth(text: tagText, font: tagFont, height: tagHeight)
        let tag = TagLabel(frame: CGRectMake(100, 100, tagWidth, tagHeight))
        tag.text = tagText
        tag.font = tagFont
        view.addSubview(tag)
    }
    
    func tagLabelTextWidth(text text: String, font: UIFont, height: CGFloat) -> CGFloat {
        let label = UILabel(frame: CGRectMake(0, 0, CGFloat.max, height))
        label.font = font
        label.text = text
        label.sizeToFit()
        return label.frame.size.width + TagLabel().tagPadding * 2
    }
    
}
```

以下のような表示がこれでできる。

<img width="525" alt="スクリーンショット 2015-12-03 0.49.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/1795/da995e30-ff0e-47f1-4b9a-c334f605f1e7.png">

## 特定のエリアに複数のタグを並べる
今度はこのタグを特定のエリアに複数並べる。
タグとなるキーワード群を`words`という文字列の配列で表現。

先ほど利用した`TagLabel`のインスタンスを`placeTagsOn(_:tags:)`メソッドで複数個生成し、特定の`UIView`(下記のコード中の`tagsView`)に`addSubView`していく。タグを並べる間隔は縦方向も横方向も10pxに設定。

* 表示エリア`tagsView`の中でのタグのoriginを設定するため、`tagOriginX`, `tagOriginY`を宣言
* 先ほどと同じくタグの横幅を`tagLabelTextWidth(text:font:height:)`で計算
* この横幅が表示エリアの横幅を超えていたら、超過した長さを切り捨てて表示エリアの横幅と同値に
* 表示エリアの横方向の余白 (`areaWidth - tagOriginX`) がタグの横幅よりも小さい時、改行して表示したいので`tagOriginX`, `tagOriginY`の値を変更
    * 改行して左端から表示するので`tagOriginX`は0に
    * `tagOriginY`に、改行した分の高さ（`tagHeight` + `tagMargin`）を加える
* `tagOriginX`, `tagOriginY`を使って`TagLabel`を`addSubview`
* 追加したタグ幅(`tagWidth + tagMargin`)の大きさを、`tagOriginX`に加える

`placeTagsOn(_:tags:)`でこれらの処理を繰り返し行うことで、複数のタグを特定のエリア内に配置している。

```swift:ViewController.swift
let words = [
    "Ruby",
    "Ruby on Rails",
    "JavaScript",
    "Swift",
    "iOS",
    "HTML",
    "CSS",
    "Perl",
    "Python",
    "PHP",
    "Java",
    "Scala",
    "Go",
    "Elixir",
    "Objective-C"
]

override func viewDidLoad() {
    super.viewDidLoad()
    
    // (略)
    
    let tagsView = UIView(frame: CGRectMake(50, 200, view.bounds.size.width - 50 * 2, 200))  // 高さは適当な大きさに
    view.addSubview(tagsView)
    placeTagsOn(tagsView, tags: words)
}

func placeTagsOn(tagsView: UIView, tags: [String]) {
    let areaWidth = tagsView.bounds.size.width
    let tagMargin: CGFloat = 10
    let tagFont = UIFont.systemFontOfSize(16)
    let tagHeight = tagFont.lineHeight + TagLabel().tagPadding * 2
    
    var tagOriginX: CGFloat = 0
    var tagOriginY: CGFloat = 0
    
    for tag in tags {
        var tagWidth = tagLabelTextWidth(text: tag, font: tagFont, height: tagHeight)
        if tagWidth > areaWidth {
            tagWidth = areaWidth
        }
        
        if areaWidth - tagOriginX < tagWidth {
            tagOriginX = 0
            tagOriginY += tagHeight + tagMargin
        }
        
        let label = TagLabel(frame: CGRectMake(tagOriginX, tagOriginY, tagWidth, tagHeight))
        label.text = tag
        label.font = tagFont
        tagsView.addSubview(label)
        
        tagOriginX += tagWidth + tagMargin
    }
}
```

表示は以下のようになり、タグが同間隔で並んでいるのがわかる。

<img width="493" alt="スクリーンショット 2015-12-03 13.53.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/1795/79c70cf6-226d-40f3-fbb5-09988069731b.png">