如何将图像放在UIButton中文本的右侧?

jas*_*ori 284 layout user-interface uibutton ios

如果可以避免,我不想使用子视图.我想要一个UIButton背景图片,文字和图像.现在,当我这样做时,图像位于文本的左侧.背景图像,文本和图像都具有不同的突出显示状态.

Lia*_*Jie 543

最简单的解决方案

iOS 10及以上,Swift:

button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
Run Code Online (Sandbox Code Playgroud)

在iOS 10之前,Swift/Obj-C:

button.transform = CGAffineTransformMakeScale(-1.0, 1.0);
button.titleLabel.transform = CGAffineTransformMakeScale(-1.0, 1.0);
button.imageView.transform = CGAffineTransformMakeScale(-1.0, 1.0);
Run Code Online (Sandbox Code Playgroud)

  • 我用它来导航栏标题视图,有一个小故障.它首次加载时很好,但当你按下一个视图控制器并弹出它时,标题会被翻转. (8认同)
  • 设置“semanticContentAttribute”的致命缺陷是它*会*破坏画外音导航。画外音导航使用语义内容属性来确定元素导航的方向,强制翻转语义意味着用户将到达按钮,然后翻转他们的 VO 导航,然后返回到刚刚访问的元素,而不是下一个元素一。 (4认同)
  • @rohinb @ jose920405尝试将ImageEdgeInsets和ContentEdgeInsets设置为填充(请注意它们已被反转)。例如`button.ImageEdgeInsets = new UIEdgeInsets(0,-leftPadding,0,leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0,0,0,leftPadding);`。在Xamarin中,但是应该足够容易地转换为Swift / Obj-C。 (2认同)

Vic*_*ius 232

更新XCODE 9(通过Interface Builder)

Interface Builder提供了一种更简单的方法.选择UIButton并在View Utilities中选择此选项:

在此输入图像描述

而已!好又简单!

可选 - 第2步:

如果要调整图像和标题之间的间距,可以在此处更改图像插入:

在此输入图像描述

希望有所帮助!

  • 请不要这样操作-这会中断从右到左语言的本地化。 (3认同)
  • 在Xcode 9.0 beta 5(9M202q)中,您遗憾地只在运行时看到结果 - 在故事板中它仍然显示左侧的图像.另请注意,因此需要一些试验和错误来设置正确的插入. (2认同)

Ben*_*min 221

尽管一些建议的答案非常有创意且极其聪明,但最简单的解决方案如下:

button.semanticContentAttribute = UIApplication.shared
    .userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft
Run Code Online (Sandbox Code Playgroud)

就如此容易.作为奖励,图像将位于从右到左区域的左侧.

编辑:由于问题已被问过几次,这是iOS 9 +.

  • 我无法相信这个答案是被接受的答案.没有人为他们的申请做本地化? (76认同)
  • 当您不希望在RTL语言中"翻转"布局时,情况并不多.直接设置`semanticContentAttribute`只是一个黑客/解决方法,而不是一个真正的解决方案. (11认同)
  • 我的方法是你不知道提出问题的人在构建什么,所以总是更好地计算布局的灵活性. (4认同)
  • 如果将按钮添加到条形按钮项目,则不起作用 (3认同)
  • @pallzoltan:这回答了这个问题(即"如何将图像放在UIButton文本的右侧?").本地化与此有什么关系? (3认同)
  • @Zoltán本地化不是问题,只需根据当前语言环境反转属性即可。 (2认同)
  • 这是如何被接受的答案?这不是最简单的,甚至不是_remotely_。Apple的UIUserInterfaceLayoutDirection.rightToLeft文档指出:“布局方向从右到左。当在诸如阿拉伯语或希伯来语的本地化环境下运行时,该值应适当,而用户界面布局原点应位于坐标系的右边缘。” UIButton有一个`imageEdgeInsets`属性,可以在代码或IB中设置。为此*专门*指定。这是重新放置按钮图像的正确方法。 (2认同)

Ben*_*ron 169

对UIButton进行子类化是完全没必要的.相反,您可以简单地为图像插入设置一个高左插入值,并为标题设置一个小的右插入.像这样的东西:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);
Run Code Online (Sandbox Code Playgroud)

  • 它工作,但只记得今天使用autolayout你必须在viewDidAppear上而不是在viewDidLoad上 (3认同)

jas*_*ori 90

我给了Inspire48这个奖励.根据他的建议并查看另一个问题,我提出了这个问题.子类UIButton并覆盖这些方法.

@implementation UIButtonSubclass

- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGRect frame = [super imageRectForContentRect:contentRect];
    frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) -  self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame;
}

- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGRect frame = [super titleRectForContentRect:contentRect];
    frame.origin.x = CGRectGetMinX(frame) - CGRectGetWidth([self imageRectForContentRect:contentRect]);
    return frame;
}

@end
Run Code Online (Sandbox Code Playgroud)

  • 事实并非如此,文档明确提到了子类化,并提供了应该覆盖自定义布局行为的方法. (48认同)
  • UIButton是一个类集群,不应该是子类. (3认同)
  • https://developer.apple.com/library/ios/documentation/uikit/reference/UIButton_Class/UIButton/UIButton.html`buttonWithType``如果您继承UIButton,则此方法不会返回您的子类的实例.如果要创建特定子类的实例,则必须直接分配/初始化按钮`和`backgroundRectForBounds`提供自定义背景装饰的子类可以覆盖此方法并返回修改的边界矩形以防止按钮覆盖任何自定义内容.既没有提到那些具体的方法,但我认为他们不介意子类. (2认同)

Pio*_*sik 76

只需在标题更改时更新插图.您需要在另一侧用相等且相反的插图补偿插入.

[thebutton setTitle:title forState:UIControlStateNormal];
thebutton.titleEdgeInsets = UIEdgeInsetsMake(0, -thebutton.imageView.frame.size.width, 0, thebutton.imageView.frame.size.width);
thebutton.imageEdgeInsets = UIEdgeInsetsMake(0, thebutton.titleLabel.frame.size.width, 0, -thebutton.titleLabel.frame.size.width);
Run Code Online (Sandbox Code Playgroud)

  • 你可能想在之前添加`[thebutton.titleLabel sizeToFit];`.如果没有触发布局,宽度可能为零.图像大小也一样(只使用UIImage.size而不是imageView大小) (2认同)

bar*_*dog 59

截至2016年1月,所有这些答案都是不必要的.在Interface Builder中,将View Semantic设置为Force Right-to-Left,或者如果您更喜欢以编程方式,semanticContentAttribute = .forceRightToLeft这将导致图像显示在文本的右侧.

  • 可悲的是,它不支持9岁以上的ios.还是很好的回答,求你了. (5认同)
  • 如果您支持辅助功能,请勿使用此选项,因为这会破坏 VoiceOver 在屏幕上说出的元素的顺序。 (2认同)

Gen*_*kin 52

在界面构建器中,您可以为UIButton配置选项Edge Insets,分别为三个部分:内容,图像,标题

在此输入图像描述 在此输入图像描述

Xcode 8:

在此输入图像描述

  • 实际上最好的答案在我看来http://stackoverflow.com/a/39013315/1470374)) (2认同)

Jea*_*ste 25

更新:Swift 3

class ButtonIconRight: UIButton {
    override func imageRect(forContentRect contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRect(forContentRect: contentRect)
        imageFrame.origin.x = super.titleRect(forContentRect: contentRect).maxX - imageFrame.width
        return imageFrame
    }

    override func titleRect(forContentRect contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRect(forContentRect: contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = super.imageRect(forContentRect: contentRect).minX
        }
        return titleFrame
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 2的原始答案:

使用Swift实现示例处理所有水平对齐的解决方案.如果需要,只需转换为Objective-C即可.

class ButtonIconRight: UIButton {
    override func imageRectForContentRect(contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRectForContentRect(contentRect)
        imageFrame.origin.x = CGRectGetMaxX(super.titleRectForContentRect(contentRect)) - CGRectGetWidth(imageFrame)
        return imageFrame
    }

    override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRectForContentRect(contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = CGRectGetMinX(super.imageRectForContentRect(contentRect))
        }
        return titleFrame
    }
}
Run Code Online (Sandbox Code Playgroud)

另外值得注意的是它处理得非常好的图像和标题插入.

灵感来自jasongregori回答;)


Mar*_*ngs 16

我决定不使用标准按钮图像视图,因为提议的移动它的解决方案感觉很笨拙。这让我获得了所需的美感,并且通过更改约束来重新定位按钮是很直观的:

extension UIButton {
    func addRightIcon(image: UIImage) {
        let imageView = UIImageView(image: image)
        imageView.translatesAutoresizingMaskIntoConstraints = false

        addSubview(imageView)

        let length = CGFloat(15)
        titleEdgeInsets.right += length

        NSLayoutConstraint.activate([
            imageView.leadingAnchor.constraint(equalTo: self.titleLabel!.trailingAnchor, constant: 10),
            imageView.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0),
            imageView.widthAnchor.constraint(equalToConstant: length),
            imageView.heightAnchor.constraint(equalToConstant: length)
        ])
    }
}
Run Code Online (Sandbox Code Playgroud)

带右箭头的按钮


小智 14

iOS 15 带来了更新,您现在可以以更简单、更杂乱的方式处理按钮中的图像位置,即。没有插图。

在 XIB/故事板中: 在编辑器中修改按钮图像位置 在向按钮添加图像属性后,只需将按钮“放置”属性设置为leading/training/top/bottom。由于它是引导/训练,所以它还有一个支持 RTL 的优势

**在代码中(以编程方式):** 以编程方式使用按钮配置属性 按钮配置,以编程方式

这不是向后兼容的功能,并且仅适用于 iOS15+,正如 WWDC '21 中演示的那样 - https://developer.apple.com/videos/play/wwdc2021/10064/?time=236

开发者文档:https://developer.apple.com/documentation/uikit/uibutton/configuration? changes=_4

  • 使用代码代替图像 (3认同)

tt.*_*lew 9

如果需要在UIBarButtonItem中完成此操作,则应使用视图中的其他包装.
这将起作用

let view = UIView()
let button = UIButton()
button.setTitle("Skip", for: .normal)
button.setImage(#imageLiteral(resourceName:"forward_button"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.sizeToFit()
view.addSubview(button)
view.frame = button.bounds
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: view)
Run Code Online (Sandbox Code Playgroud)

这不行

let button = UIButton()
button.setTitle("Skip", for: .normal)
button.setImage(#imageLiteral(resourceName:"forward_button"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.sizeToFit()
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
Run Code Online (Sandbox Code Playgroud)


Naz*_*san 8

自己做。Xcode10、swift4、

用于以编程方式进行 UI 设计

在此处输入图片说明

 lazy var buttonFilter : ButtonRightImageLeftTitle = {
    var button = ButtonRightImageLeftTitle()
    button.setTitle("Playfir", for: UIControl.State.normal)
    button.setImage(UIImage(named: "filter"), for: UIControl.State.normal)
    button.backgroundColor = UIColor.red
    button.contentHorizontalAlignment = .left
    button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
    return button
}()
Run Code Online (Sandbox Code Playgroud)

边缘插入值应用于矩形以缩小或扩展由该矩形表示的区域。通常,在视图布局期间使用边缘插入来修改视图的框架。正值会导致帧插入(或收缩)指定的量。负值会导致框架开始(或扩展)指定的数量。

class ButtonRightImageLeftTitle: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        guard imageView != nil else { return }

        imageEdgeInsets = UIEdgeInsets(top: 5, left: (bounds.width - 35), bottom: 5, right: 5)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: -((imageView?.bounds.width)! + 10), bottom: 0, right: 0 )

    }
}
Run Code Online (Sandbox Code Playgroud)

用于 StoryBoard UI 设计

在此处输入图片说明 在此处输入图片说明


Wil*_*ich 8

我的意思是,我认为这里最简单的解决方案只是告诉按钮水平布局“填充”按钮的宽度,而不是像.left您最初想到的那样对齐:

contentHorizontalAlignment = .fill
Run Code Online (Sandbox Code Playgroud)

应该在这里解决问题。只要确保你告诉你的按钮有一个尾随图像位置:configuration.imagePlacement = .trailing,你应该得到以下结果:

在此输入图像描述

只需将您发送configuration.contentInsets到您喜欢的任何位置即可为按钮提供一些美观的填充。


Vit*_*nko 7

这是UIButton中心对齐内容的解决方案.此代码使图像右对齐,允许使用imageEdgeInsetstitleEdgeInsets进行宝贵的定位.

在此输入图像描述

UIButton使用自定义类的子类并添加:

- (CGRect)imageRectForContentRect:(CGRect)contentRect {
    CGRect frame = [super imageRectForContentRect:contentRect];
    CGFloat imageWidth = frame.size.width;
    CGRect titleRect = CGRectZero;
    titleRect.size = [[self titleForState:self.state] sizeWithAttributes:@{NSFontAttributeName: self.titleLabel.font}];
    titleRect.origin.x = (self.frame.size.width - (titleRect.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    frame.origin.x = titleRect.origin.x + titleRect.size.width - self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame;
}

- (CGRect)titleRectForContentRect:(CGRect)contentRect {
    CGFloat imageWidth = [self imageForState:self.state].size.width;
    CGRect frame = [super titleRectForContentRect:contentRect];
    frame.origin.x = (self.frame.size.width - (frame.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    return frame;
}
Run Code Online (Sandbox Code Playgroud)


cno*_*gr8 6

由于转换解决方案在 iOS 11 中不起作用,我决定编写一种新方法。

调整按钮semanticContentAttribute为我们提供了很好的右侧图像,而无需在文本更改时重新布局。因此,它是理想的解决方案。但是我仍然需要 RTL 支持。应用程序无法在同一会话中更改其布局方向这一事实很容易解决此问题。

话虽如此,这很简单。

extension UIButton {
    func alignImageRight() {
        if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
            semanticContentAttribute = .forceRightToLeft
        }
        else {
            semanticContentAttribute = .forceLeftToRight
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mus*_*tri 5

延伸方式

使用扩展名在右侧使用自定义偏移设置图像

   extension UIButton {
    func addRightImage(image: UIImage, offset: CGFloat) {
        self.setImage(image, for: .normal)
        self.imageView?.translatesAutoresizingMaskIntoConstraints = false
        self.imageView?.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
        self.imageView?.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -offset).isActive = true
    }
}
Run Code Online (Sandbox Code Playgroud)