Reputation: 2163
I m very new to IOS development and AutoLayout . I am facing issues to align the Image and Text inside UIbutton using Storyboard. I had tried to achieve it with TitleEdgeinset and ImageEdge insets accordingly to place the Title ( text ) vertically centered below the Image. But the issue is I have 3 similar buttons which are Vertically stacked ( StackView) and the Text is dynamically set since we have localized strings ( includes Arabic rtl ) . The image and text moves according to the text length. Is there any ways that I can achieve to make all the buttons with image and text vertically alligned.Also, different screen resolutions are not currently working if using edge insets. Appreciate your help . Thanks in advance.
Upvotes: 9
Views: 18791
Reputation: 1
You can use this Custom Class
class VerticalButton: UIButton {
private let stackView = UIStackView()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setup()
}
private func setup() {
stackView.axis = .vertical
stackView.alignment = .center
stackView.spacing = 5 // Adjust spacing between image and title
stackView.isUserInteractionEnabled = false
addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: centerYAnchor),
stackView.widthAnchor.constraint(equalTo: widthAnchor),
stackView.heightAnchor.constraint(equalTo: heightAnchor)
])
}
override func setImage(_ image: UIImage?, for state: UIControl.State) {
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFit
stackView.addArrangedSubview(imageView)
}
override func setTitle(_ title: String?, for state: UIControl.State) {
let titleLabel = UILabel()
titleLabel.text = title
titleLabel.textAlignment = .center
titleLabel.font = self.titleLabel?.font
stackView.addArrangedSubview(titleLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
stackView.frame = bounds
}
}
How to Use:
@IBOutlet weak var btnOutlet: VerticalButton!
btnOutlet.setImage(UIImage(named: "Image-Name"), for: .normal)
btnOutlet.setTitle("Title", for: .normal)
Upvotes: -1
Reputation: 3647
If you are using iOS 15.0 you can use:
// Create a button
let button = UIButton(type: .custom)
// Configure the button using UIButton.Configuration
var config = UIButton.Configuration.filled()
config.titlePadding = 10
config.imagePlacement = .top // this is whats makes the magic
config.imagePadding = 10
button.configuration = config
Upvotes: 2
Reputation: 5939
Combining Ajay's and Matej's answer:
import Foundation
import UIKit
class VerticalButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
self.contentHorizontalAlignment = .left
}
override func layoutSubviews() {
super.layoutSubviews()
centerButtonImageAndTitle()
}
private func centerButtonImageAndTitle() {
let titleSize = self.titleLabel?.frame.size ?? .zero
let imageSize = self.imageView?.frame.size ?? .zero
let spacing: CGFloat = 6.0
self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing),left: 0, bottom: 0, right: -titleSize.width)
self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0)
}
}
Upvotes: 5
Reputation: 257
I created a view, then put a VStack with image and text, as well as button. Make sure the VStack constraints are 0 on all 4 sides so it covers the button :)
Upvotes: 0
Reputation: 773
This is a solution that worked for me. Just set the button class to HorizontallyCenteredButton
in storyboard and set the title and image top and bottom insets according to your needs (to place the image higher than title) and the button will adjust horizontal insets automatically so that the image is centered above title.
class HorizontallyCenteredButton: LocalizedButton {
override func awakeFromNib() {
super.awakeFromNib()
self.contentHorizontalAlignment = .left
}
override func layoutSubviews() {
super.layoutSubviews()
self.centerButtonImageAndTitle()
}
func centerButtonImageAndTitle() {
let size = self.bounds.size
let titleSize = self.titleLabel!.frame.size
let imageSize = self.imageView!.frame.size
self.imageEdgeInsets = UIEdgeInsets(top: self.imageEdgeInsets.top, left: size.width/2 - imageSize.width/2, bottom: self.imageEdgeInsets.bottom, right: 0)
self.titleEdgeInsets = UIEdgeInsets(top: self.titleEdgeInsets.top, left: -imageSize.width + size.width/2 - titleSize.width/2, bottom: self.titleEdgeInsets.bottom, right: 0)
}
}
Upvotes: 1
Reputation: 13547
I've modified Ajay's answer because my images weren't centered:
func centerButtonImageAndTitle(button: UIButton) {
let spacing: CGFloat = 5
let titleSize = button.titleLabel!.frame.size
let imageSize = button.imageView!.frame.size
button.titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0)
button.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: -imageSize.width/2, bottom: 0, right: -titleSize.width)
}
Upvotes: 1
Reputation: 5554
this is an easy one, so apologies if you have already tried it!
you don't need to set anything for insets, just make sure that the 3 buttons are aligned with horizontal centres ...
select the controls you want to align, and click on the button highlighted below (bottom right on the xCode screen) and select the Vertical Centres option to align the three with each other, or select Horizontally in Container to put them in the middle of your view.
Upvotes: -1
Reputation: 1827
Few days ago, I solved similar problem,try this
private func adjustImageAndTitleOffsetsForButton (button: UIButton) {
let spacing: CGFloat = 6.0
let imageSize = button.imageView!.frame.size
button.titleEdgeInsets = UIEdgeInsetsMake(0, -imageSize.width, -(imageSize.height + spacing), 0)
let titleSize = button.titleLabel!.frame.size
button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0, 0, -titleSize.width)
}
call this method for each button, like
self.adjustImageAndTitleOffsetsForButton(yourButton)
Upvotes: 26
Reputation: 1136
To align all the buttons vertically, first select the buttons, then click the button on the bottom-right of the storyboard titled "Align", and finally select "Vertical Centers" in the menu that appears. That should do the trick.
Upvotes: 0