UIButtonのimageViewは左、titleLabelは右に配置されるのが一般的です。
その配置を逆にしようとした時に少し苦戦したので、備忘録として記載します。
環境
Xcode 11.6
Swift 5.2
titleLabelとimageViewを左右逆に配置する
imageViewを右、titleLabelを左に配置したい場合、UIButtonを左右反転することで配置することができます。
その際、imageViewやtitleLabelも反転してしまい、文字や画像まで反対になってしまうので、それぞれをもう一度左右反転させて元に戻します。
let button = UIButton()
// Buttonを左右反転させる
transform = CGAffineTransform(scaleX: -1, y: 1)
// 文字が反転するため、titleLabelを左右反転させ元に戻す
titleLabel?.transform = CGAffineTransform(scaleX: -1, y: 1)
// imageが反転するため、imageViewを左右反転させ元に戻す
imageView?.transform = CGAffineTransform(scaleX: -1, y: 1)
左右反転させたUIButtonにbackgroundImageをセットする
背景が単なる単色の場合は上記で想定通りのボタンが完成します。
しかし、背景にも画像を用いる場合にはもう一工夫が必要です。
上記の対応ではUIButton自体は左右反転した状態のため、そのまま button.setBackgroundImage(_:for:)
してしまうと背景画像も反転したまま表示されてしまいます。
用意した画像 | そのまま背景画像をセットした結果 |
---|---|
画像を正しい向きで表示させたい場合、左右反転させた状態の画像をsetBackgroundImageすることで対応できます。
let button = UIButton()
// titleLabelとimageViewの位置を反転させるためにbuttonを反転させる時にbackgroundImageも反転されてしまうため、反転させた画像をセットする
let backgroundImage = UIImage(named: "background.png")?.withHorizontallyFlippedOrientation()
button.setBackgroundImage(backgroundImage, for: .normal)
サンプルコード
titleLabelとimageViewを左右逆に配置させたUIButtonのサンプルは、Playgroundを使って以下のコードで試せます。
import UIKit
import PlaygroundSupport
final class SampleButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
setTitle("サンプル", for: .normal)
setTitleColor(.white, for: .normal)
let image = UIImage(named: "image.png")
setImage(image, for: .normal)
imageView?.contentMode = .scaleAspectFit
// titleLabelとimageViewの位置を反転させるためにbuttonを反転させる時にbackgroundImageも反転されてしまうため、反転させた画像をセットする
let backgroundImage = UIImage(named: "background.png")?.withHorizontallyFlippedOrientation()
setBackgroundImage(backgroundImage, for: .normal)
// Buttonを左右反転させる
transform = CGAffineTransform(scaleX: -1, y: 1)
// 文字が反転するため、titleLabelを左右反転させ元に戻す
titleLabel?.transform = CGAffineTransform(scaleX: -1, y: 1)
// imageが反転するため、imageViewを左右反転させ元に戻す
imageView?.transform = CGAffineTransform(scaleX: -1, y: 1)
// 左右反転させているため、左側に設定したい値をrightに、右側に設定したい値をleftに設定する
contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
imageEdgeInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 4)
titleEdgeInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
PlaygroundPage.current.liveView = SampleButton(frame: CGRect(x: 0, y: 0, width: 150, height: 50))