51
48

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSアプリで、吹き出しっぽいviewを作成

Posted at

人(キャラクター)が喋っている感じを表現しようと、吹き出しを描いた際のメモ。
Xcode7.2で動作確認しています。

方針としては、グラフィックスコンテキストを作成して、吹き出しぽい形を描画していくのが良さそう。
グラフィックスコンテキストを利用した描画に関しての説明は、以下の記事などが詳しい。

SwiftでCoreGraphics画像作成(基本)【メモ】 - Qiita

実装

StoryBoardに置いたViewController.swiftに、吹き出しをaddSubview(_:)する。
吹き出しは、BalloonViewというUIViewのサブクラスとして宣言し、幅280px, 高さ100pxで描画。

ViewController.swift
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let balloon = BalloonView(frame: CGRectMake((view.bounds.size.width - 280) / 2, 100, 280, 100))
        balloon.backgroundColor = UIColor.whiteColor()
        view.addSubview(balloon)      
    }
    
}

BalloonViewの中身は以下の通り。

drawRect(_:)メソッドの中で、

  • グラフィックスコンテキストを宣言
    • UIGraphicsGetCurrentContextで呼び出し
  • 吹き出しを塗りつぶす色を指定
    • それぞれCGContextSetFillColorWithColor
  • 吹き出しの塗りつぶし範囲の指定 & 実行
    • contextBalloonPath(_:rect:)メソッドで

塗りつぶしについて。

今回描こうと思っている吹き出しは、長方形部分と三角形部分に分割できる。
contextBalloonPath(_:rect:)メソッドの中では、三角形部分の座標を計算し、それを利用して塗りつぶしを行う。
※三角形の一辺の長さを20px, 高さを17.3pxで、だいたい正三角形

  1. CGContextAddRect(_:_:)で長方形部分のpathを指定
  2. CGContextMoveToPoint(_:_:_:), CGContextAddLineToPoint(_:_:_:)で三角形のpathを指定
    • 算出済みの三角形の各頂点の座標を利用

これらをそれぞれCGContextFillPath(_:)で塗りつぶし、吹き出しが完成。

BalloonView.swift
class BalloonView: UIView {
    
    let triangleSideLength: CGFloat = 20
    let triangleHeight: CGFloat = 17.3
    
    override func drawRect(rect: CGRect) {
        super.drawRect(rect)
        
        let context = UIGraphicsGetCurrentContext()
        CGContextSetFillColorWithColor(context, UIColor.greenColor().CGColor)
        contextBalloonPath(context!, rect: rect)
    }
    
    func contextBalloonPath(context: CGContextRef, rect: CGRect) {
        let triangleRightCorner = (x: (rect.size.width + triangleSideLength) / 2, y: CGRectGetMaxY(rect) - triangleHeight)
        let triangleBottomCorner = (x: rect.size.width / 2, y: CGRectGetMaxY(rect))
        let triangleLeftCorner = (x: (rect.size.width - triangleSideLength) / 2, y: CGRectGetMaxY(rect) - triangleHeight)
        
        // 塗りつぶし
        CGContextAddRect(context, CGRectMake(0, 0, 280, rect.size.height - triangleHeight))
        CGContextFillPath(context)
        CGContextMoveToPoint(context, triangleLeftCorner.x, triangleLeftCorner.y)
        CGContextAddLineToPoint(context, triangleBottomCorner.x, triangleBottomCorner.y)
        CGContextAddLineToPoint(context, triangleRightCorner.x, triangleRightCorner.y)
        CGContextFillPath(context)
    }
    
}

以下のようなビューになる。

スクリーンショット 2015-12-27 20.18.18.png

吹き出しに枠線をつけたい場合は、CGContextStrokePath(_:)などを使って実装することになるだろう。

蛇足

せっかくなので、セリフと喋ってるキャラクター(というか猫)の写真だけ入れてみた。
セリフはUILabel、写真はUIImageViewで実装してaddSubViewしてるだけです。

ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    
    let balloon = BalloonView(frame: CGRectMake((view.bounds.size.width - 280) / 2, 100, 280, 100))
    balloon.backgroundColor = UIColor.whiteColor()
    view.addSubview(balloon)
    
    let label = UILabel(frame: balloon.bounds)
    label.frame.origin.y -= 8.7
    label.text = "ニャーオ"
    label.textColor = UIColor.whiteColor()
    label.font = UIFont.boldSystemFontOfSize(24)
    label.textAlignment = .Center
    balloon.addSubview(label)
    
    let imageView = UIImageView()
    imageView.frame.size = CGSizeMake(100, 100)
    imageView.frame.origin.y = CGRectGetMaxY(balloon.frame) + 10
    imageView.center.x = balloon.center.x
    imageView.layer.cornerRadius = 50
    imageView.image = UIImage(named: "Cat")
    imageView.contentMode = .ScaleAspectFill
    imageView.clipsToBounds = true
    view.addSubview(imageView)
}

出来上がり。以上です。

スクリーンショット 2015-12-27 20.21.21.png

51
48
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
51
48

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?