読者です 読者をやめる 読者になる 読者になる

酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

NSTextAttachmentが含まれているNSAttributedStringでは行間をあけることができない

UILabelで「画像+複数行のテキスト」を実装したいが、行間の調整をすることができず頭を抱えていました。ミニマムコードで現象が再現するのか、このエントリを書きながら調査ました。

結論を先に書くと、NSTextAttachmentにもlineSpacingを設定する必要があるでした。

問題の現象

下図は、NSTextAttachmentを含んだNSAttributedStringを表示させています。

f:id:ch3cooh393:20170310134424p:plain

コードは下記のようになっている。

func setMultipleText() {        
    let str = NSMutableAttributedString()
    
    //プロ生ちゃんアイコンを追加する
    let number = NSTextAttachment()
    if let image = UIImage(named: "sd06") {
        number.image = image
        number.bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
    }
    str.append(NSAttributedString(attachment: number))
    
    //長いテキストを追加する
    let longText = "プロ生ちゃん「ああああ(...省略...)あああ」"
    
    let style = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
    let font = UIFont.boldSystemFont(ofSize: 19)
    style.minimumLineHeight = font.lineHeight + 30
    style.maximumLineHeight = font.lineHeight + 30
    
    let attr: [String : Any] = [
        NSFontAttributeName: font,
        NSParagraphStyleAttributeName: style
    ]
    let longTextString = NSAttributedString(string: longText, attributes: attr)
    str.append(longTextString)
    
    //ラベルにNSAttributedStringを設定する
    label.attributedText = str
}

プロ生ちゃんアイコンを追加する処理をコメントアウトにして実行ます。

//        //プロ生ちゃんアイコンを追加する
//        let number = NSTextAttachment()
//        if let image = UIImage(named: "sd06") {
//            number.image = image
//            number.bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
//        }
//        str.append(NSAttributedString(attachment: number))

画像だけにした場合はきちんと行間が開きます。

f:id:ch3cooh393:20170310134920p:plain

ここまで調査して、NSTextAttachmentが含まれているNSAttributedStringでは行間をあけることができないのではないか?と考えました。同じようなケースでハマっている人も見かけませんでした。

解決した

NSTextAttachment分まで含めて属性を設定することで、NSTextAttachmentが含まれているNSAttributedStringでも行間を開けることができました。

func setMultipleText() {        
    let str = NSMutableAttributedString()
    
    //プロ生ちゃんアイコンを追加する
    let number = NSTextAttachment()
    if let image = UIImage(named: "sd06") {
        number.image = image
        number.bounds = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
    }
    str.append(NSAttributedString(attachment: number))
    
    //長いテキストを追加する
    let longText = "プロ生ちゃん「ああああ(...省略...)あああ」"
    str.append(NSAttributedString(string: longText))
    
    //属性を設定する
    let style = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
    let font = UIFont.boldSystemFont(ofSize: 19)
    style.minimumLineHeight = font.lineHeight + 30
    style.maximumLineHeight = font.lineHeight + 30
    
    let attr: [String : Any] = [
        NSFontAttributeName: font,
        NSParagraphStyleAttributeName: style
    ]
    
    //属性を付与する
    str.addAttributes(attr, range: NSRange(location: 0, length: str.length))
    
    //ラベルにNSAttributedStringを設定する
    label.attributedText = str
}

上記のコードを実行すると、下図のようになります。

f:id:ch3cooh393:20170310135936p:plain

lineSpacingを使う

持ってくるコードが悪くてここまでminimumLineHeight、maximumLineHeightを使って1行あたりのサイズを調整していました。スクリーンショットを撮り直すのが面倒なのでこのエントリではそのままにしておきます。

行間をあけるのであれば、lineSpacingの方が適切ですね。

 //属性を設定する
    let style = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
    let font = UIFont.boldSystemFont(ofSize: 19)
//        style.minimumLineHeight = font.lineHeight + 30
//        style.maximumLineHeight = font.lineHeight + 30
    style.lineSpacing = 30

上記のコードを実行すると、下図のようになります。

f:id:ch3cooh393:20170310140133p:plain

関連記事