LoginSignup
39
28

More than 5 years have passed since last update.

iOSでチラシっぽい価格レイアウトを再現してみた

Posted at

概要

TwitterでフォロワーさんがUIStackViewで挑戦してたのを見かけた。

スレッドを遡ってみると、NSAttributedStringで実装できるんじゃないかという話があり、興味が湧いたので挑戦してみた。

作ったもの

文字のサイズ感は目見当。

chirashi.png

//
//  ViewController.swift
//  Price
//
//  Created by macneko on 2018/09/07.
//  Copyright © 2018年 macneko. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let label = UILabel()
        self.view.addSubview(label)

        label.frame = self.view.frame
        label.textAlignment = .center

        let fontSize: CGFloat = 80
        let font = UIFont.systemFont(ofSize: fontSize)
        let attributeText = NSMutableAttributedString(string: "各種¥(税込)280",
                                                      attributes: [.font: font, .foregroundColor: UIColor.red])
        // 各種
        attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.4),
                                     .baselineOffset: 2],
                                    range: NSRange(location: 0, length: 2))
        // ¥
        attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.6),
                                     .kern: -50],
                                    range: NSRange(location: 2, length: 1))
        // (税込)
        attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.2),
                                     .baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 4],
                                    range: NSRange(location: 3, length: 4))
        // ()のベースライン調整
        attributeText.addAttributes([.baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 3],
                                    range: NSRange(location: 3, length: 1))
        attributeText.addAttributes([.baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 3],
                                    range: NSRange(location: 6, length: 1))
        label.attributedText = attributeText
    }

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

説明

ソースコードを部分的に切り出して処理内容を説明する。

let fontSize: CGFloat = 80
let font = UIFont.systemFont(ofSize: fontSize)
let attributeText = NSMutableAttributedString(string: "各種¥(税込)280",
                                              attributes: [.font: font, .foregroundColor: UIColor.red])

はじめに attributeText に基本的な装飾と文字列を格納しておいて、装飾を変更したい部分をNSRangeで指定して、加工していく方法をとることにした。

// 各種
attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.4),
                             .baselineOffset: 2],
                            range: NSRange(location: 0, length: 2))

各種 の部分。
文字サイズは基本サイズの40%の大きさを指定。
や数字よりベースラインが少し下にずれて見えるので、.baselineOffset: 2 を指定して少し上にずらした。
ベースラインについては ラテン文字と欧文組版 をP14の図を参照。
雑に説明すると、.baselineOffset に正の数を与えると上に移動し、負の数を与えると下に移動する。

// ¥
attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.6),
                             .kern: -50],
                            range: NSRange(location: 2, length: 1))

の部分。
文字サイズは基本サイズの60%の大きさを指定。
.kern: -50 を指定して、次の文字の ( との字間を詰めた。
雑に説明すると、.kern (カーニング)は当該文字と次の文字の文字間のアキを詰める設定。
なお、パーレンにはカーニングが適用されないっぽかったので、を前にもってきてカーニング設定をしている。

// (税込)
attributeText.addAttributes([.font: UIFont.systemFont(ofSize: fontSize * 0.2),
                             .baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 4],
                            range: NSRange(location: 3, length: 4))

(税込) の部分。
文字サイズは基本サイズの20%の大きさを指定。
ベースラインは相対値で計算したものの、それだけではうまく揃わなかったので、微調整している。

// ()のベースライン調整
attributeText.addAttributes([.baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 3],
                            range: NSRange(location: 3, length: 1))
attributeText.addAttributes([.baselineOffset: (fontSize * 0.8) - (fontSize * 0.2) - 3],
                            range: NSRange(location: 6, length: 1))

() の部分。
ベースラインが揃わなかったので、この部分だけさらに微調整した。

文字列ごとにNSAttributedStringKeyを指定していき、最後に結合する方法でも良かったんだけど、DTP的な手法のほうが手慣れているため、この方法にしてしまったがゆえに、すごくIllustratorやInDesignを触っている気分になった。

まとめ

参考

Mastering TextKit

39
28
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
39
28