How to Draw a Speech Bubble in Swift 2.0
03 Sep 2015
Here’s a quick example of how to create a custom UIView
to display a speech bubble in Swift 2.0 just like this:
Step 1: Subclass UIView
Firstly, you need to subclass UIView
as follows.
If you intended to use storyboard , ensure that you replace the fatalError
line with super.init(coder: aDecoder)
class SpeechBubble : UIView {
var color : UIColor = UIColor . grayColor ()
override init ( frame : CGRect ) {
super . init ( frame : frame )
}
required init ?( coder aDecoder : NSCoder ) {
fatalError ( "init(coder:) has not been implemented" )
}
}
Step 2: Override drawRect(rect: CGRect)
Do not call super.drawRect(rect)
in this method!
override func drawRect ( rect : CGRect ) {
let rounding : CGFloat = rect . width * 0.02
//Draw the main frame
let bubbleFrame = CGRect ( x : 0 , y : 0 , width : rect . width , height : rect . height * 2 / 3 )
let bubblePath = UIBezierPath ( roundedRect : bubbleFrame , byRoundingCorners : UIRectCorner . AllCorners , cornerRadii : CGSize ( width : rounding , height : rounding ))
//Color the bubbleFrame
color . setStroke ()
color . setFill ()
bubblePath . stroke ()
bubblePath . fill ()
//Add the point
let context = UIGraphicsGetCurrentContext ()
//Start the line
CGContextBeginPath ( context )
CGContextMoveToPoint ( context , CGRectGetMinX ( bubbleFrame ) + bubbleFrame . width * 1 / 3 , CGRectGetMaxY ( bubbleFrame ))
//Draw a rounded point
CGContextAddArcToPoint ( context , CGRectGetMaxX ( rect ) * 1 / 3 , CGRectGetMaxY ( rect ), CGRectGetMaxX ( bubbleFrame ), CGRectGetMinY ( bubbleFrame ), rounding )
//Close the line
CGContextAddLineToPoint ( context , CGRectGetMinX ( bubbleFrame ) + bubbleFrame . width * 2 / 3 , CGRectGetMaxY ( bubbleFrame ))
CGContextClosePath ( context )
//fill the color
CGContextSetFillColorWithColor ( context , color . CGColor )
CGContextFillPath ( context );
}
}
Step 3: Add a convenience initializer
Now we just need to add a convenience initializer so we can change the default color if required.
required convenience init ( withColor frame : CGRect , color : UIColor ? = . None ) {
self . init ( frame : frame )
if let color = color {
self . color = color
}
}
You can now instantiate a speech bubble with a color as follows:
let speechBubble = SpeechBubble ( withColor : CGRect ( x : 0 , y : 0 , width : 200 , height : 200 ), color : . redColor ())
Of course, you can easily tweak this class to make it more flexible, such as customizing how rounded the edges are or adding a UILabel
to display the number of comments etc.
Here’s the full class for reference:
class SpeechBubble : UIView {
var color : UIColor = UIColor . grayColor ()
override init ( frame : CGRect ) {
super . init ( frame : frame )
}
required init ?( coder aDecoder : NSCoder ) {
fatalError ( "init(coder:) has not been implemented" )
}
required convenience init ( withColor frame : CGRect , color : UIColor ? = . None ) {
self . init ( frame : frame )
if let color = color {
self . color = color
}
}
override func drawRect ( rect : CGRect ) {
let rounding : CGFloat = rect . width * 0.02
//Draw the main frame
let bubbleFrame = CGRect ( x : 0 , y : 0 , width : rect . width , height : rect . height * 2 / 3 )
let bubblePath = UIBezierPath ( roundedRect : bubbleFrame , byRoundingCorners : UIRectCorner . AllCorners , cornerRadii : CGSize ( width : rounding , height : rounding ))
//Color the bubbleFrame
color . setStroke ()
color . setFill ()
bubblePath . stroke ()
bubblePath . fill ()
//Add the point
let context = UIGraphicsGetCurrentContext ()
//Start the line
CGContextBeginPath ( context )
CGContextMoveToPoint ( context , CGRectGetMinX ( bubbleFrame ) + bubbleFrame . width * 1 / 3 , CGRectGetMaxY ( bubbleFrame ))
//Draw a rounded point
CGContextAddArcToPoint ( context , CGRectGetMaxX ( rect ) * 1 / 3 , CGRectGetMaxY ( rect ), CGRectGetMaxX ( bubbleFrame ), CGRectGetMinY ( bubbleFrame ), rounding )
//Close the line
CGContextAddLineToPoint ( context , CGRectGetMinX ( bubbleFrame ) + bubbleFrame . width * 2 / 3 , CGRectGetMaxY ( bubbleFrame ))
CGContextClosePath ( context )
//fill the color
CGContextSetFillColorWithColor ( context , color . CGColor )
CGContextFillPath ( context );
}
}
Happy coding.