UILabelで「画像+複数行のテキスト」を実装したいが、行間の調整をすることができず頭を抱えていました。ミニマムコードで現象が再現するのか、このエントリを書きながら調査ました。
結論を先に書くと、NSTextAttachmentにもlineSpacingを設定する必要があるでした。
問題の現象
下図は、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 = "プロ生ちゃん「ああああ(...省略...)あああ」" 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))
画像だけにした場合はきちんと行間が開きます。
ここまで調査して、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 }
上記のコードを実行すると、下図のようになります。
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
上記のコードを実行すると、下図のようになります。
関連記事
関連記事
このほかにもiOSアプリ開発で見つけたネタや悩んだ内容など紹介しています。Tipsをまとめておりますのでこちらのページをご参照ください。