shigeki.takeguchi.log

アラフィフおじさんの技術日記

文章の先頭や末尾にアイコン画像をつけるってやつをSwiftで比較的簡単にやってみる

Webサイトなどではよく文章の先頭にアイコン画像をつけることでリンク先や文章内容を類推しやすくして読ませるってことをよくやってますね。
Yahoo! JAPANのトップページでも左カラムに各サービスへのリンクエリアを設けて先頭へ各サービスのアイコン画像を配置したりトピックなどでも末尾にカメラアイコンやNEW、またビデオ再生のアイコン画像を配置してリンク先のコンテンツには写真があるよとかビデオがあるよなどを類推しやすくしていますね。

CSSで背景に画像を配置して左パディングすることで実現したりafterやbefore疑似要素を使って配置することが一般的によくやる方法だったりします。比較的簡単にできHTMLコードへ直接画像を置くことによる弊害もありませんね。
これをiOSアプリでやろうってなるとちょっと面倒だったりします。
アプリでも文字表示って細かくコントロールしようとすると面倒です。そう考えるとHTML+CSSって文字要素を柔軟に扱いやすくしてくれてます。

でSwift3で書いてみましたがNSMutableAttributedStringってのを使うと文字にいろいろと装飾がつけれます。
FonwAwesomeKitを利用して星型のアイコン画像を作ってます。
またアイコン画像と文章にパディングをつけたかったので透明のアイコン画像をつくってます。
全角や半角スペースを挿入すればまあそれなりのスペースは作れますがなんとなく空き文字をいれるってのはアクセシビリティ的にも避けたかったのでこうしました。
最後にlabel(UILabel)のattributedTextにいれます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
let iconSize: CGFloat = 13.0
let starIcon = FAKFontAwesome.starIcon(withSize: iconSize)
starIcon?.addAttribute(NSForegroundColorAttributeName, value: UIColor.red)
let starIconImage = (starIcon?.image(with: CGSize(width:iconSize, height: iconSize)))! as UIImage

let muAttString = NSMutableAttributedString.init(string: "10,000")

//アイコン画像を先頭につけたテキストにします
let txtAtt = NSTextAttachment.init()
txtAtt.image = starIconImage
txtAtt.bounds = CGRect(x: 0, y: -1, width: iconSize, height: iconSize)
let attAttString = NSAttributedString.init(attachment: txtAtt)
muAttString.insert(attAttString, at: 0)

//アイコン画像を先頭につけたテキストにします
let txtAttEmpty = NSTextAttachment.init()
let paddingWidth = iconSize * 0.2

//空きの塗りつぶし画像を作ります
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: paddingWidth, height: iconSize))
UIGraphicsBeginImageContextWithOptions(size, false, 0)
UIColor.clear.setFill()
UIRectFill(rect)
let emptyImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
txtAttEmpty.image = emptyImage
txtAttEmpty.bounds = CGRect(x: 0, y: -2, width: paddingWidth, height: iconSize)
let attAttStringEmpty = NSAttributedString.init(attachment: txtAttEmpty)
muAttString.insert(attAttStringEmpty, at: 1)

//ラベルにテキストを設定します
label.attributedText = muAttString

なんども使うようならclass化した方が使い勝手よいですよね。 色で塗りつぶしたUIimageをつくるgetImageWithColorとわけて使っています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import UIKit

class Utils: NSObject {

//空きの塗りつぶし画像を返す
class func getImageWithColor(color: UIColor, size: CGSize) -> UIImage {
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: size.width, height: size.height))
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(rect)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}

//アイコン付きテキスト(NSMutableAttributedString)を返す
class func getInsertIconString(string: String, iconImage: UIImage, iconSize: CGFloat) -> NSMutableAttributedString {

let muAttString = NSMutableAttributedString.init(string: string)

//アイコン画像を先頭につけたテキストにします
let txtAtt = NSTextAttachment.init()
txtAtt.image = iconImage
txtAtt.bounds = CGRect(x: 0, y: -1, width: iconSize, height: iconSize)
let attAttString = NSAttributedString.init(attachment: txtAtt)
muAttString.insert(attAttString, at: 0)

//アイコン画像の左に余白をつけたテキストにします
let txtAttEmpty = NSTextAttachment.init()
let paddingWidth = iconSize * 0.2
txtAttEmpty.image = Utils.getImageWithColor(color: UIColor.clear, size: CGSize(width: paddingWidth, height: iconSize))
txtAttEmpty.bounds = CGRect(x: 0, y: -2, width: paddingWidth, height: iconSize)
let attAttStringEmpty = NSAttributedString.init(attachment: txtAttEmpty)
muAttString.insert(attAttStringEmpty, at: 1)

return muAttString
}
}

Utils.swiftというファイルでclass化します。

1
2
3
4
5
6
let iconSize: CGFloat = 13.0
let starIcon = FAKFontAwesome.starIcon(withSize: iconSize)
starIcon?.addAttribute(NSForegroundColorAttributeName, value: UIColor.red)
let starIconImage = (starIcon?.image(with: CGSize(width: iconSize, height: iconSize)))! as UIImage
//先頭にアイコン画像をつけたい文字列とアイコン画像を引数で渡します
label.attributedText = Utils.getInsertIconString(string: "10,000", iconImage: starIconImage, iconSize: iconSize)

こっちは呼び出し元ですね。

ここのところワンカットで撮影した散歩動画をYouTubeで配信してます。商店街や飲み屋街から観光地、城跡、坂など好奇心のおもむくまま撮影してます。動画を気に入ったらYouTubeのチャンネルも観てもらえると嬉しいです。https://www.youtube.com/c/shigekitakeguchi