Help us understand the problem. What is going on with this article?

UIButtonのtitleLabelとimageViewを左右逆に配置する

UIButtonのimageViewは左、titleLabelは右に配置されるのが一般的です。
その配置を逆にしようとした時に少し苦戦したので、備忘録として記載します。

環境

Xcode 11.6
Swift 5.2

titleLabelとimageViewを左右逆に配置する

imageViewを右、titleLabelを左に配置したい場合、UIButtonを左右反転することで配置することができます。
その際、imageViewやtitleLabelも反転してしまい、文字や画像まで反対になってしまうので、それぞれをもう一度左右反転させて元に戻します。

button.png

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:) してしまうと背景画像も反転したまま表示されてしまいます。

用意した画像 そのまま背景画像をセットした結果
background.png スクリーンショット 2020-09-03 16.21.36.png

画像を正しい向きで表示させたい場合、左右反転させた状態の画像をsetBackgroundImageすることで対応できます。

let button = UIButton()

// titleLabelとimageViewの位置を反転させるためにbuttonを反転させる時にbackgroundImageも反転されてしまうため、反転させた画像をセットする
let backgroundImage = UIImage(named: "background.png")?.withHorizontallyFlippedOrientation()
button.setBackgroundImage(backgroundImage, for: .normal)

SampleButton.png

サンプルコード

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))
kurapy-n
iOSエンジニア。Google Apps Scriptが好きです。
fablic
満足度No.1 のフリマアプリ「ラクマ」を運営しています。
https://fril.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした