Creating a Chat Bubble Which Looks Like a Chat Bubble in iMessage — the advanced way

This article is the second of two articles about creating (iMessage style) chat bubbles.

The first article is available here.

In this tutorial, we’ll look at an advanced way to create chat bubble with tail.

This tutorial was created using Swift 4.1 and Xcode 9.2. The source code is available on Github.

This tutorial will teach you how to create a chat bubble with tail which looks like chat bubbles in iMessage. But this article is not about creating a fully fledged chat app. I’m going to focus specifically on how to create dynamically sized bubbles in the advanced way. Let’s start!

Implementation Approach

  1. We’ll create an instance of UIBezierPath which looks like a chat bubble
  2. And resize this path depending on the size of our content
  3. We’ll calculate the size of our text content using boundingRect(with size: CGSize, options: NSStringDrawingOptions = [], attributes: [NSAttributedStringKey : Any]? = nil, context: NSStringDrawingContext?) -> CGRect method of an instance of String

Drawing Bezier Path

We can create this path manually. But a much simpler way is to use PaintCode. With this excellent app you can convert any vector image to native Swift code.

I’ve saved the bubble image which I created in previous lesson as SVG, and then imported it in PaintCode.

This code was generated by PaintCode. It draws a path which looks like our bubble on SVG image.

Creating the Speech Bubble

Add an implementation of showOutgoingMessage() in ViewController and its call in viewWillAppear().

In showOutgoingMessage() add the code generated by PaintCode. Also create an instance of CAShapeLayer and use our bezierPath as a path of this instance.

Build and run.

Not bad. Let’s try to change the height of our bubble (which is now equal to 34) to variable height.

Do the same for our bubble’s width (which is now equal to 68).

And the final stage. Add an instance of UILabel, and calculate its sizes depending on its text and font using boundingRect(with size: CGSize, options: NSStringDrawingOptions = [], attributes: [NSAttributedStringKey : Any]? = nil, context: NSStringDrawingContext?) -> CGRect.

Creating the Image Bubble

Add an implementation of showIncomingMessage() in ViewController and its call in viewWillAppear().

In showIncomingMessage() add a bezier path for an incoming message.

Change the width and the height of our bubble to width and height variables respectively.

And the final part. Add an instance of UIImageView which we’ll be using to contain our image. And assign our incomingMessageLayer to mask property of an imageView’s layer.

Nice work!

UPD

This article has prompted me to add a small update.

If you want to implement your speech bubble as an UIView instance (rather than a CAShapeLayer instance) you can use draw(_:) method.

Create BubbleView inherited from UIView, and override its draw(_:) instance method.

Also change showIncomingMessage() and showOutgoingMessage(text: String) implementations respectively.

You can find these changes in the bubble_view branch from the source code repository.

The Source Code

The source code from this tutorial is available on Github.

Like what you read? Give Dima a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.