LoginSignup
4
4

More than 5 years have passed since last update.

【Swift】FontAwesome 5を使ったバッジを作ってみた

Last updated at Posted at 2019-01-18

しずおかオンラインで「まちぽスタンプ」というスタンプラリーができるiOSアプリを開発しているKazuomatzです。

このアプリで、スタンプラリーのミッションを達成すると、iPhoneのアクティビティやPokémon GOのように報酬としてバッジが貰えると楽しいと思い、バッジの実装を行いました。
バッジには色々なアイコンを表示したいですよね。そのため、色と絵柄を自由に組み合わせで様々なバッジを作るためのライブラリを考えました。
アイコンをひとつひとつ作成するのは現実的ではないので、Web開発ではお馴染みのFontAwesomeの豊富なアイコンを使って実現したいと思いました。

最終的にできあがったアプリの画面は、こんな感じ。

何となくバッジ感があってよい感じです。

スタンプラリーを管理する管理コンソールでアイコンと色を選択してバッジを設定しておきます。そのスタンプラリーのミッションを達成するとバッジを取得できる仕掛けです。

このような形で、カラーとFontAwesomeのフォント名を選択して設定します。アプリとはAPIでカラーコードとフォント名とでインタフェイスを取っています。

api.json(例)
{
   "badge_title" : "ミッションクリア",
   "badge_color" : "#ed6d46",
   "badge_icon"  : "fa-spoon"
}

このアプリを開発した時点では、FontAwesome 4.7を使いましたが、時代はFontAwesome 5なので、FontAwesome5 対応にして、githubで公開しましたので紹介します。

AwesomeBadge

サンプルアプリはgithubからダウンロードできます。

CocoaPodsでも使えます。

Podfile
pod 'AwesomeBadge'

内部でFontAwesomeのラッパーライブラリーFontAwesome.swiftを使用しています。

使い方

使い方はこんな感じです。

hoge.swift
import AwesomeBadge

let badgeView = AwesomeBadgeView(
            fontStyle: .brands,            // font awesome style .solid / .regular / .brands
            fontName: "fa-android",        // font awesome font name 'fa-xxxxx'
            frame: CGRect(x:0, y:0, width: 100,height: 100),
            backgroundColor: "#a4c639"     // Color (Hex String)
        )
self.view.addSubView(badgeView)       

  • FontAwesome 5 は、スタイルがsolid / regular / brandsから選択できますので、スタイルを選択できます。
  • fontNameは文字列で指定します。FontAwesome.swiftでは、フォント名がすべてenumで定義されていますが、APIでのやりとりを考えるとStringの方が何かと便利なので、引数はフォント名をStringで指定するようにしました。同じ理由で、色もUIColorではなくStringとしています。
hoge.swift
let badgeView = AwesomeBadgeView(
            fontStyle: .brands,            // font awesome style .solid / .regular / .brands
            fontName: "fa-android",        // font awesome font name 'fa-xxxxx'
            frame: CGRect(x:0, y:0, width: 100,height: 100),
            backgroundColor: "#a4c639"     // Color (Hex String)
            gradient: false               // not add GradientLayer
        )
self.view.addSubView(badgeView)       

こちらはお好みですが、gradient = false にするとグラデーションのないフラットなバッジになります。

hoge.swift
@IBOutlet weak var badgeView:AwesomeBadgeView!

badgeView.drawBadge(
    fontStyle: .solid,
    fontName: "fa-star-and-crescent",
    radius: 200,
    backgroundColor: "#273751",
    gradient: true,
    foregroundColor: "#f4e242"
)

Interface BuilderでAwesomeBadgeViewを埋め込む場合は、drawBadgeをコールします。
foregroundColorも指定できます(デフォルトは#ffffff)。

実装について

実際にBadgeを作成しているコードは以下の通りです。

AwesomeBadgeView.swift
public func drawBadge(fontStyle:FontStyle ,fontName:String, radius:CGFloat, backgroundColor:String, gradient:Bool = true, foregroundColor:String = "ffffff") {

        // 再呼び出しを考慮して、SubViewをすべて削除
        self.subviews.forEach { (view) in
            view.removeFromSuperview()
        }

        self.backgroundColor = UIColor(hex: backgroundColor)
        self.clipsToBounds = true
        self.backgroundColor = .clear
        self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: radius, height: radius)

        // バッジの縁
        let boderWidth:CGFloat = radius * 0.08
        let backgroundView:UIView = UIView(frame:self.frame)

        // バッジの縁を20%暗い色にする
        backgroundView.backgroundColor = UIColor(hex: backgroundColor).darker(by: 20)
        backgroundView.layer.cornerRadius = radius / 2

        // フォント画像を配置するView
        let badgeBackgroundViewFrame = CGRect(x: boderWidth, y: boderWidth,width: radius - boderWidth * 2, height: radius - boderWidth * 2)
        let badgeBackgroundView = UIView(frame: badgeBackgroundViewFrame)
        badgeBackgroundView.layer.cornerRadius = (radius - boderWidth * 2) / 2
        badgeBackgroundView.clipsToBounds = true
        badgeBackgroundView.backgroundColor = UIColor(hex: backgroundColor)

        // 指定があればグレデーションのLayerを追加します。
        if gradient {
            let color = UIColor(hex: backgroundColor)
            let gradientLayer:CAGradientLayer = CAGradientLayer(layer: badgeBackgroundView.layer)
            gradientLayer.frame = badgeBackgroundView.bounds
            gradientLayer.colors = [
                color.lighter(by:60)?.cgColor as Any,
                color.cgColor  as Any,
                color.darker(by:30)?.cgColor as Any
            ]
            gradientLayer.cornerRadius = (radius - boderWidth * 2) / 2
            badgeBackgroundView.layer.addSublayer(gradientLayer)
        }

        // スタイル、フォント名を指定して、フォントが描画されたUIImageViewを取得します。
        let iconSize = CGSize(width: radius - boderWidth * 4, height: radius - boderWidth * 4)
        let imageView:UIImageView = UIImageView(frame:CGRect(x:0,y:0,width:radius - boderWidth * 2, height:radius - boderWidth * 2))
        imageView.contentMode = .center

        let faFontName = FontAwesomeIcons[fontName]
        if  faFontName != nil {
            let image = UIImage.fontAwesomeIcon(name: FontAwesome(rawValue: faFontName!)!, style: FontAwesomeStyle(rawValue: fontStyle.rawValue)!, textColor: UIColor(hex:foregroundColor), size: iconSize)
            imageView.image = image
            imageView.backgroundColor = .clear
            imageView.layer.cornerRadius = (radius - boderWidth * 2) / 2
        }
        badgeBackgroundView.addSubview(imageView)
        backgroundView.addSubview(badgeBackgroundView)
        self.addSubview(backgroundView)
    }

やっていることを図解するとこんなイメージになります。
AwesomeBadge.png

手軽にバッジを生成できるので、アプリのアクセントとして使ってみて下さい。

4
4
0

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
4
4