使用自动布局约束垂直对齐图像和文本的按钮

问题描述 投票:0回答:9

我对 IOS 开发和 AutoLayout 非常陌生。 我面临使用 Storyboard 对齐 UIbutton 内的图像和文本的问题。我尝试使用 TitleEdgeinset 和 ImageEdge insets 来实现它,将标题(文本)垂直居中放置在图像下方。但问题是我有 3 个类似的按钮,它们是垂直堆叠的(StackView),并且文本是动态设置的,因为我们已经本地化了字符串(包括阿拉伯语 rtl)。 图像和文本根据文本长度移动。有什么方法可以实现使所有带有图像和文本的按钮垂直对齐。此外,如果使用边缘插图,当前无法使用不同的屏幕分辨率。感谢您的帮助。预先感谢。

ios swift autolayout
9个回答
26
投票

前几天,我解决了类似的问题,试试这个

 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)
}

为每个按钮调用此方法,例如

self.adjustImageAndTitleOffsetsForButton(yourButton)

5
投票

结合 Ajay 和 Matej 的答案:

UIButton with vertically aligned image and text

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)
 }
}

2
投票

如果您使用的是 iOS 15.0,您可以使用:

// 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

1
投票

我修改了Ajay的答案,因为我的图像没有居中:

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)
}

1
投票

这是一个对我有用的解决方案。只需在情节提要中将按钮类设置为

HorizontallyCenteredButton
,并根据您的需要设置标题和图像顶部和底部插图(将图像放置在标题上方),按钮将自动调整水平插图,使图像位于标题上方居中.

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)
    }
}

0
投票

要垂直对齐所有按钮,首先选择按钮,然后单击故事板右下角标题为“对齐”的按钮,最后在出现的菜单中选择“垂直居中”。这应该可以解决问题。


0
投票

Button with vertical image and text

我创建了一个视图,然后放置一个带有图像和文本的VStack,以及按钮。 确保 VStack 约束在所有 4 条边上均为 0,这样它就覆盖了按钮:)


0
投票

您可以使用这个自定义类

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
    
    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
}
}

使用方法:

 @IBOutlet weak var btnOutlet: VerticalButton!

 btnOutlet.setImage(UIImage(named: "Image-Name"), for: .normal)
 btnOutlet.setTitle("Title", for: .normal)

-1
投票

这是一个简单的方法,如果您已经尝试过,我们深表歉意!

您不需要为插图设置任何内容,只需确保 3 个按钮与水平中心对齐... Add New Alignment Constraints

选择要对齐的控件,然后单击下面突出显示的按钮(xCode 屏幕右下角),然后选择“垂直中心”选项将三个控件相互对齐,或者选择“在容器中水平放置”将它们放在控件的中间你的看法。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.