Home > Mobile >  UIButton title and image positions are swapped unexpectedly on clicked
UIButton title and image positions are swapped unexpectedly on clicked

Time:07-10

I'd like to make a button that the image is on the right instead of the left side.

This is the expected layout: enter image description here

I'm able to satisfy the layouts with the following code:

import UIKit

class ViewController: UIViewController {

    private lazy var leftButton: UIButton = {
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.addTarget(self, action: #selector(didTap), for: .touchUpInside)

        button.setImage(UIImage(systemName: "trash"), for: .normal)
        button.setTitle("Trash", for: .normal)

        button.setTitleColor(.systemBlue, for: .normal)

        if let imageView = button.imageView {
            imageView.contentMode = .scaleAspectFit

            NSLayoutConstraint.activate([
                imageView.widthAnchor.constraint(equalToConstant: 8),
                imageView.heightAnchor.constraint(equalToConstant: 8)
            ])
        }

        button.contentHorizontalAlignment = .left
        button.contentVerticalAlignment = .center
        button.semanticContentAttribute = .forceRightToLeft

        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftButton)
    }

    @objc private func didTap() {

    }
}

Everything looked exactly what I wanted at the beginning until I clicked the button. The positions of the title and the image were swapped. Please take a look at the gif:

enter image description here

Does anyone have any clue on why this happened? And how can I improve my code?

I guess it may have something to do with the navigation item.

CodePudding user response:

Try it like this:

    let button = UIButton(type: .system)
    button.setTitle("Trash", for: .normal)
    button.setImage(UIImage(systemName: "trash"), for: .normal)
    button.setPreferredSymbolConfiguration(
        .init(scale: .small), forImageIn: .normal
    )
    button.widthAnchor.constraint(equalToConstant: 60).isActive = true
    button.imageEdgeInsets.right = -75
    button.titleEdgeInsets.left = -35
    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: button)

However, if you can confine yourself to iOS 15 and later, this is a lot more simple and coherent, because the notion of a trailing image is built right in:

    var config = UIButton.Configuration.plain()
    config.title = "Trash"
    config.image = UIImage(systemName: "trash")?
        .applyingSymbolConfiguration(.init(scale: .small))
    config.imagePlacement = .trailing
    let button = UIButton(configuration: config)
    navigationItem.leftBarButtonItem = UIBarButtonItem(customView: button)
  • Related