SwiftUIでTextの中にImageをインラインで表示する
SwiftUIでアイコン画像とテキストを組み合わせて表示するには、HStackやLabelが使われることが多いが、今回は次のようにTextの中にImageをインラインで表示する方法を紹介する。
インラインでImageを表示する
TextにはImageから初期化するイニシャライザがあり、他のTextと連結して画像を表示することができる(公式ドキュメント)。
// Textを結合してインラインでImageを表示
(Text(Image(systemName: "book.fill")) + Text("テキスト"))
// 変数の埋め込みでもOK
Text("\\(Image(systemName: "book.fill"))テキスト")
しかし、Asset Catalogに追加した画像リソースを使用する場合、Textは画像を元のサイズで表示するようで、画像リソースのサイズが大きい場合、テキストサイズと合わなくなってしまう。
そこで、一度画像をUIImageとして初期化して、こちらのextensionのようにUIImageをリサイズすれば、テキストサイズに合わせたインライン表示ができる。注意したいのは、UIImage.resize後にUIImage.RenderingMode.alwaysTemplateを指定しないと、foregroundStyleでカラー指定しても画像に反映されない。
struct ContentView: View {
var body: some View {
// UIImageとして読み込んで、リサイズ・テンプレートとしてレンダリングすることで、フォントサイズに合うように表示できる
if let catIcon = catIcon {
(Text(Image(uiImage: catIcon)) + Text("テキスト"))
.font(.system(size: 14))
.foregroundStyle(Color.blue)
.padding()
}
}
private var catIcon: UIImage? {
UIImage(named: "cat")?
.resize(size: .init(width: 14, height: 14))?
.withRenderingMode(.alwaysTemplate)
}
}
extension UIImage {
func resize(size _size: CGSize) -> UIImage? {
let widthRatio = _size.width / size.width
let heightRatio = _size.height / size.height
let ratio = widthRatio < heightRatio ? widthRatio : heightRatio
let resizedSize = CGSize(width: size.width * ratio, height: size.height * ratio)
UIGraphicsBeginImageContextWithOptions(resizedSize, false, 0.0)
draw(in: CGRect(origin: .zero, size: resizedSize))
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage
}
}
参考
この記事が気に入ったらサポートをしてみませんか?