LoginSignup
0
1

More than 5 years have passed since last update.

Swift2 FontAwesomeアイコンとテキストを併用したボタンを作成する

Posted at

今回作りたかったのは下の画像のボタンです。
sample.png

FontAwesome Swiftをよく利用させてもらっているのですが、画像のようなサンプルが見当たらなかったので自作していました。
iOSアプリ制作を初めてまだ時間が経っていないので、いい作りとは言えないのですが、ひとまず思った通りのことまでできたため、コードの掲載をします。

このサンプルコードの中で、やっつけでやってしまっている箇所が2箇所あります。

  1. 左右にテキストとアイコンを配置したときに生じる、ベースラインずれの差を埋めるための方法が観測値から算出した計算値になっていて、この計算根拠が目視を用いたものになっているため、環境によって多分に微妙なずれが生じる可能性が高いこと
  (シミュレータでiOS4 / iOS5 / iOS6 / iPad Air)での目視確認テストをしたところ、
  画像と同様の表示が確認できたため、実用上問題はなさそうという判断をして使っています。
  1. 上下アイコンのボタンの配置を2重改行で対応してしまっていること
 Paragraphでline heightを設定し、TextAlignをCenterにしておけば自然と中央揃えになるかと
 見込んでいたのですが、アイコンだけ左端に表示される現象が確認され、改行を与えた場合に
 期待通りの表示になったため、サンプルソース上では2重改行で余白調整をしてしまっています。
 こちらも1と同様に調整のための修正が非常にイケテナイので、
 あくまで参考として利用いただくのがよいかと思います。

NSMutableAttributedStringの利用例の一つになり、制作のアイデアの一つになれればよいかなと。

こうしたらやっつけじゃなくなったよ!!というご意見は大絶賛募集しております。。。

以下コード
```UIFontAwesomeButton.swift
import UIKit
import FontAwesome_swift

enum AwesomeIconAlignment {
case top
case bottom
case left
case right
}

@IBDesignable
class UIFontAwesomeButton: UIButton {

func setAwesomeMixTitle(awesomeFontType: FontAwesome, AwesomeFontSize: CGFloat, titleText: String, iconAlign: AwesomeIconAlignment = .left, AwesomeFontColor: UIColor! = nil, titleTextFontName: String = "", titleTextFontSize: CGFloat = 0, titleTextColor: UIColor! = nil) {

    // Awesomefontの設定
    let afColor = AwesomeFontColor == nil ? self.titleLabel?.textColor : AwesomeFontColor
    let btnIcon = String.fontAwesomeIconWithName(awesomeFontType)
    var btnAttr = NSMutableAttributedString(string: btnIcon)
    btnAttr.addAttributes([NSForegroundColorAttributeName: afColor], range: NSMakeRange(0, btnIcon.characters.count))
    btnAttr.addAttributes([NSFontAttributeName: UIFont.fontAwesomeOfSize(AwesomeFontSize)], range: NSMakeRange(0, btnIcon.characters.count))

    // 通常テキスト設定
    let titleAttributeText = NSMutableAttributedString(string: titleText)
    let fontName = titleTextFontName == "" ? self.titleLabel?.font.fontName : titleTextFontName
    let fontSize = titleTextFontSize <= 0 ? self.titleLabel?.font.pointSize : titleTextFontSize
    if titleText != "" {
        let txtColor = titleTextColor == nil ? self.titleLabel?.textColor : titleTextColor
        titleAttributeText.addAttributes([NSFontAttributeName: UIFont(name: fontName!, size: fontSize!)!], range: NSMakeRange(0, titleText.characters.count))
        titleAttributeText.addAttributes([NSForegroundColorAttributeName: txtColor], range: NSMakeRange(0, titleText.characters.count))
    }

    switch iconAlign {
    case .top:
        let separaterChar = NSMutableAttributedString(string: "\n\n")
        separaterChar.addAttributes([NSFontAttributeName: UIFont(name: fontName!, size: fontSize! * 0.3)!], range: NSMakeRange(0, separaterChar.length))
        btnAttr.appendAttributedString(separaterChar)
        btnAttr.appendAttributedString(titleAttributeText)
    case .bottom:
        let separaterChar = NSMutableAttributedString(string: "\n\n")
        separaterChar.addAttributes([NSFontAttributeName: UIFont(name: fontName!, size: fontSize! * 0.3)!], range: NSMakeRange(0, separaterChar.length))

        separaterChar.appendAttributedString(btnAttr)
        titleAttributeText.appendAttributedString(separaterChar)
        btnAttr = titleAttributeText
    case .left:
        let baseLineHieght:CGFloat = getBaseLineHeight(AwesomeFontSize, fontSize: fontSize!)
        if AwesomeFontSize >= fontSize! {
            titleAttributeText.addAttribute(NSBaselineOffsetAttributeName, value: baseLineHieght, range: NSMakeRange(0, titleAttributeText.length))
        } else if AwesomeFontSize < fontSize! {
            btnAttr.addAttribute(NSBaselineOffsetAttributeName, value: baseLineHieght, range: NSMakeRange(0, btnAttr.length))
        }
        btnAttr.appendAttributedString(titleAttributeText)
    case .right:
        let baseLineHieght:CGFloat = getBaseLineHeight(AwesomeFontSize, fontSize: fontSize!)
        if AwesomeFontSize > fontSize! {
            titleAttributeText.addAttribute(NSBaselineOffsetAttributeName, value: baseLineHieght, range: NSMakeRange(0, titleAttributeText.length))
        } else if AwesomeFontSize < fontSize! {
            btnAttr.addAttribute(NSBaselineOffsetAttributeName, value: baseLineHieght, range: NSMakeRange(0, btnAttr.length))
        }
        titleAttributeText.appendAttributedString(btnAttr)
        btnAttr = titleAttributeText
    }

    self.titleLabel?.numberOfLines = 0
    self.titleLabel?.textAlignment = .Center
    self.setAttributedTitle(btnAttr, forState: .Normal)
}

/**
 テキストとFontawesomeのサイズが異なるとベースライン下基準になってしまうため、垂直中央によるようにLineHeightを計算する。
 計算は fontawesome / 2 - font / 2 でフォントを中央分割した後での高さの差を求め、その値の平方根を取得し、
 さらにその平方根の平方根を足した値になる。値の根拠は観察値から導き出したものであるので、環境の変化に非常に弱い。
 よって適用する環境をよく観察してオフセット値の算出をする必要がある。

 - parameter AwesomeFontSize: FontAwesomeのフォントサイズ
 - parameter fontSize:        テキストのフォントサイズ

 - returns: ベースラインオフセット
 */
private func getBaseLineHeight(AwesomeFontSize: CGFloat, fontSize: CGFloat) -> CGFloat {
    var baseLineHieght:CGFloat = sqrt(abs(AwesomeFontSize / 2 - fontSize / 2)) + sqrt(sqrt(abs(AwesomeFontSize / 2 - fontSize / 2)))
    if abs(AwesomeFontSize / 2 - fontSize / 2) > 10.0 {
        baseLineHieght = baseLineHieght + sqrt(sqrt(abs(AwesomeFontSize / 2 - fontSize / 2)))
    } else if baseLineHieght == 0 {
        baseLineHieght = 0.5
    }
    return baseLineHieght
}

// viewの枠線の色
@IBInspectable var borderColor: UIColor = UIColor.clearColor() {
    didSet {
        self.layer.borderColor = borderColor.CGColor
    }
}

// viewの枠線の太さ
@IBInspectable var borderWidth: CGFloat = 0 {
    didSet {
        self.layer.borderWidth = borderWidth
    }
}

// viewの角丸
@IBInspectable var cornerRadius: CGFloat = 0 {
    didSet {
        self.layer.cornerRadius = cornerRadius
        self.layer.masksToBounds = true
    }
}

}
```

呼び出しサンプル
``` ViewController.swift
import UIKit

class ViewController: UIViewController {
@IBOutlet weak var btnTop: UIFontAwesomeButton!
@IBOutlet weak var btnBottom: UIFontAwesomeButton!
@IBOutlet weak var btnLeft: UIFontAwesomeButton!
@IBOutlet weak var btnRight: UIFontAwesomeButton!
@IBOutlet weak var btnLeft30_12: UIFontAwesomeButton!
@IBOutlet weak var btnRight30_12: UIFontAwesomeButton!
@IBOutlet weak var btnLeft12_30: UIFontAwesomeButton!
@IBOutlet weak var btnRight12_30: UIFontAwesomeButton!
@IBOutlet weak var btnLeft46_8: UIFontAwesomeButton!
@IBOutlet weak var btnRight46_8: UIFontAwesomeButton!
@IBOutlet weak var btnLeft8_46: UIFontAwesomeButton!
@IBOutlet weak var btnRight8_46: UIFontAwesomeButton!

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    btnTop.setAwesomeMixTitle(
        .Search, AwesomeFontSize: 28
        , titleText: "上アイコン"
        , iconAlign: .top
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 14.0
        , titleTextColor: UIColor.grayColor())

    btnBottom.setAwesomeMixTitle(
        .User, AwesomeFontSize: 38
        , titleText: "下アイコン"
        , iconAlign: .bottom
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 14.0
        , titleTextColor: UIColor.grayColor())

    btnLeft.setAwesomeMixTitle(
        .User, AwesomeFontSize: 24
        , titleText: " 左アイコン"
        , iconAlign: .left
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "Helvetica Bold Oblique"
        , titleTextFontSize: 24
        , titleTextColor: UIColor.whiteColor())

    btnRight.setAwesomeMixTitle(
        .User, AwesomeFontSize: 24
        , titleText: "右アイコン "
        , iconAlign: AwesomeIconAlignment.right
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 24
        , titleTextColor: UIColor.grayColor())

    btnLeft30_12.setAwesomeMixTitle(
        .User, AwesomeFontSize: 30
        , titleText: " 左アイコン"
        , iconAlign: .left
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "Helvetica Bold Oblique"
        , titleTextFontSize: 12
        , titleTextColor: UIColor.whiteColor())

    btnRight30_12.setAwesomeMixTitle(
        .User, AwesomeFontSize: 30
        , titleText: "右アイコン "
        , iconAlign: AwesomeIconAlignment.right
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 12
        , titleTextColor: UIColor.grayColor())

    btnLeft12_30.setAwesomeMixTitle(
        .User, AwesomeFontSize: 12
        , titleText: " 左アイコン"
        , iconAlign: .left
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "Helvetica Bold Oblique"
        , titleTextFontSize: 30
        , titleTextColor: UIColor.whiteColor())

    btnRight12_30.setAwesomeMixTitle(
        .User, AwesomeFontSize: 12
        , titleText: "右アイコン "
        , iconAlign: AwesomeIconAlignment.right
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 30
        , titleTextColor: UIColor.grayColor())

    btnLeft46_8.setAwesomeMixTitle(
        .User, AwesomeFontSize: 46
        , titleText: " 左アイコン"
        , iconAlign: .left
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "Helvetica Bold Oblique"
        , titleTextFontSize: 8
        , titleTextColor: UIColor.whiteColor())

    btnRight46_8.setAwesomeMixTitle(
        .User, AwesomeFontSize: 46
        , titleText: "右アイコン "
        , iconAlign: AwesomeIconAlignment.right
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 8
        , titleTextColor: UIColor.grayColor())

    btnLeft8_46.setAwesomeMixTitle(
        .User, AwesomeFontSize: 8
        , titleText: " 左アイコン"
        , iconAlign: .left
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "Helvetica Bold Oblique"
        , titleTextFontSize: 46
        , titleTextColor: UIColor.whiteColor())

    btnRight8_46.setAwesomeMixTitle(
        .User, AwesomeFontSize: 8
        , titleText: "右アイコン "
        , iconAlign: AwesomeIconAlignment.right
        , AwesomeFontColor: UIColor.orangeColor()
        , titleTextFontName: "HiraginoSans-W3"
        , titleTextFontSize: 46
        , titleTextColor: UIColor.grayColor())
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}
```

0
1
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
0
1