简体   繁体   English

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

[英]How do I put the image on the right side of the text in a UIButton?

I don't want to use a subview if I can avoid it.如果可以避免,我不想使用子视图。 I want a UIButton with a background image, text, and an image in it.我想要一个带有背景图像、文本和图像的UIButton Right now, when I do that, the image is on the left side of the text.现在,当我这样做时,图像位于文本的左侧。 The background image, text, and image all have different highlight states.背景图像、文本和图像都有不同的高亮状态。

Simplest solution:最简单的解决方案:

iOS 10 & up, Swift: 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)

Before iOS 10, Swift/Obj-C:在 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);

iOS 9 & up, Swift: (Recommended) iOS 9 及更高版本,Swift:(推荐)

button.semanticContentAttribute = .forceRightToLeft

Despite some of the suggested answers being very creative and extremely clever, the simplest solution is as follows:尽管一些建议的答案非常有创意且非常聪明,但最简单的解决方案如下:

button.semanticContentAttribute = UIApplication.shared
    .userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft

As simple as that.就如此容易。 As a bonus, the image will be at the left side in right-to-left locales.作为奖励,图像将在从右到左的语言环境中位于左侧。

EDIT : as the question has been asked a few times, this is iOS 9 + .编辑:因为这个问题已经问过几次了,这是iOS 9 +

UPDATED FOR XCODE 9 (Via Interface Builder)更新 XCODE 9(通过接口生成器)

There's an easier way from the Interface Builder . Interface Builder 提供了一种更简单的方法。

Select the UIButton and select this option in the View Utilities > Semantic :选择 UIButton 并在 View Utilities > Semantic 中选择此选项:

左到右 在此处输入图片说明 That's it!而已! Nice and simple!好看又简单!

OPTIONAL - 2nd step:可选- 第 2 步:

If you want to adjust the spacing between the image and the title you can change the Image Inset here:如果要调整图像和标题之间的间距,可以在此处更改图像插入

在此处输入图片说明

Hope that helps!希望有帮助!

Subclassing UIButton is completely unnecessary.子类化 UIButton 是完全没有必要的。 Instead you can simply set a high left inset value for the image insets, and a small right inset for the title.相反,您可以简单地为图像插入设置一个高的左插入值,并为标题设置一个小的右插入值。 Something like this:像这样的东西:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);

I'm giving Inspire48 the credit for this one.这个功劳归功于Inspire48 Based on his suggestion and looking at that other question I came up with this.根据他的建议并查看另一个问题,我想出了这个。 Subclass UIButton and override these methods.子类化 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

Just update the insets when the title is changed.更改标题时只需更新插图。 You need to compensate for the inset with an equal and opposite inset on the other side.您需要在另一侧使用相等且相反的插图来补偿插图。

[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);

All of these answers, as of January 2016, are unnecessary.截至 2016 年 1 月,所有这些答案都是不必要的。 In Interface Builder, set the View Semantic to Force Right-to-Left , or if you prefer programmatic way, semanticContentAttribute = .forceRightToLeft That will cause the image to appear on the right of your text.在 Interface Builder 中,将 View Semantic 设置为Force Right-to-Left ,或者如果您更喜欢编程方式, semanticContentAttribute = .forceRightToLeft这将导致图像出现在文本的右侧。

In interface builder you can configure options Edge Insets for UIButton, separately each of three parts: content, image, title在界面构建器中,您可以为 UIButton 配置选项 Edge Insets,分别为三个部分:内容、图像、标题

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

Xcode 8:代码 8:

在此处输入图片说明

Update: Swift 3更新:斯威夫特 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
    }
}

Original answer for Swift 2: Swift 2 的原始答案:

A solution that handles all horizontal alignments, with a Swift implementation example.处理所有水平对齐的解决方案,带有 Swift 实现示例。 Just translate to Objective-C if needed.如果需要,只需转换为 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
    }
}

Also worth noting that it handles quite well image & title insets.同样值得注意的是,它可以很好地处理图像和标题插入。

Inspired from jasongregori answer ;)灵感来自 jasongregori 答案;)

I decided not to use the standard button image view because the proposed solutions to move it around felt hacky.我决定不使用标准按钮图像视图,因为提议的移动它的解决方案感觉很笨拙。 This got me the desired aesthetic, and it is intuitive to reposition the button by changing the constraints:这让我获得了所需的美感,并且通过更改约束来重新定位按钮是很直观的:

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

带右箭头的按钮

If this need to be done in UIBarButtonItem , additional wrapping in view should be used如果这需要在UIBarButtonItem 中完成,则应在视图中使用额外的包装
This will work这将工作

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)

This won't work这行不通

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)

Do Yourself.自己做。 Xcode10, swift4, Xcode10、swift4、

For programmatically UI design用于以编程方式进行 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
}()

Edge inset values are applied to a rectangle to shrink or expand the area represented by that rectangle.边缘插入值应用于矩形以缩小或扩展由该矩形表示的区域。 Typically, edge insets are used during view layout to modify the view's frame.通常,在视图布局期间使用边缘插入来修改视图的框架。 Positive values cause the frame to be inset (or shrunk) by the specified amount.正值会导致帧插入(或收缩)指定的量。 Negative values cause the frame to be outset (or expanded) by the specified amount.负值会导致框架开始(或扩展)指定的数量。

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 )

    }
}

for StoryBoard UI design用于 StoryBoard UI 设计

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

Here is solution for UIButton with center aligned content.这是具有居中对齐内容的UIButton解决方案。 This code make image right aligned and allows to use imageEdgeInsets and titleEdgeInsets for precious positioning.此代码使图像右对齐并允许使用imageEdgeInsetstitleEdgeInsets进行宝贵的定位。

在此处输入图片说明

Subclass UIButton with your custom class and add:使用您的自定义类将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;
}

Extension Way延伸方式

Using extension to set image on the right side with custom offset使用扩展在右侧设置带有自定义偏移量的图像

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

Being that the transform solution doesn't work in iOS 11 I decided to write a new approach.由于转换解决方案在 iOS 11 中不起作用,我决定编写一种新方法。

Adjusting the buttons semanticContentAttribute gives us the image nicely to the right without having to relayout if the text changes.调整按钮semanticContentAttribute为我们提供了很好的右侧图像,而无需在文本更改时重新布局。 Because of this it's the ideal solution.因此,它是理想的解决方案。 However I still need RTL support.但是我仍然需要 RTL 支持。 The fact that an app can not change it's layout direction in the same session resolves this issue easily.应用程序无法在同一会话中更改其布局方向这一事实很容易解决此问题。

With that said, it's pretty straight forward.话虽如此,这很简单。

extension UIButton {
    func alignImageRight() {
        if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
            semanticContentAttribute = .forceRightToLeft
        }
        else {
            semanticContentAttribute = .forceLeftToRight
        }
    }
}

Swift -Extend the UiButton and put these lines Swift - 扩展 UiButton 并放置这些行

    if let imageWidth = self.imageView?.frame.width {
        self.titleEdgeInsets = UIEdgeInsetsMake(0, -imageWidth, 0, imageWidth);
    }

    if let titleWidth = self.titleLabel?.frame.width {
        let spacing = titleWidth + 20
        self.imageEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, -spacing);
    }

Took @Piotr's answer and made it into a Swift extension.接受@Piotr 的回答并将其变成了 Swift 扩展。 Make sure to set the image and title before calling this, so that the button sizes properly.确保在调用之前设置图像和标题,以便按钮大小正确。

 extension UIButton {
    
    /// Makes the ``imageView`` appear just to the right of the ``titleLabel``.
    func alignImageRight() {
        if let titleLabel = self.titleLabel, imageView = self.imageView {
            // Force the label and image to resize.
            titleLabel.sizeToFit()
            imageView.sizeToFit()
            imageView.contentMode = .ScaleAspectFit
            
            // Set the insets so that the title appears to the left and the image appears to the right. 
            // Make the image appear slightly off the top/bottom edges of the button.
            self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -1 * imageView.frame.size.width,
                bottom: 0, right: imageView.frame.size.width)
            self.imageEdgeInsets = UIEdgeInsets(top: 4, left: titleLabel.frame.size.width,
                bottom: 4, right: -1 * titleLabel.frame.size.width)
          }
        }
     }

Building on Piotr Tomasik's elegant solution: if you want to have a bit of spacing between the button label and image as well, then include that in your edge insets as follows (copying my code here that works perfectly for me):建立在 Piotr Tomasik 的优雅解决方案之上:如果您还想在按钮标签和图像之间留出一点间距,那么将其包含在边缘插图中,如下所示(在此处复制我的代码,这对我来说非常适合):

    CGFloat spacing          = 3;
    CGFloat insetAmount      = 0.5 * spacing;

    // First set overall size of the button:
    button.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
    [button sizeToFit];

    // Then adjust title and image insets so image is flipped to the right and there is spacing between title and image:
    button.titleEdgeInsets   = UIEdgeInsetsMake(0, -button.imageView.frame.size.width - insetAmount, 0,  button.imageView.frame.size.width  + insetAmount);
    button.imageEdgeInsets   = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width + insetAmount, 0, -button.titleLabel.frame.size.width - insetAmount);

Thanks Piotr for your solution!感谢 Piotr 的解决方案!

Erik埃里克

A swift option that does what you want without playing with any insets:一个快速选项,可以在不使用任何插图的情况下执行您想要的操作:

class RightImageButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let  textSize = titleLabel?.intrinsicContentSize(),
                imageSize = imageView?.intrinsicContentSize() {
            let wholeWidth = textSize.width + K.textImageGap + imageSize.width
            titleLabel?.frame = CGRect(
                x: round(bounds.width/2 - wholeWidth/2),
                y: 0,
                width: ceil(textSize.width),
                height: bounds.height)
            imageView?.frame = CGRect(
                x: round(bounds.width/2 + wholeWidth/2 - imageSize.width),
                y: RoundRetina(bounds.height/2 - imageSize.height/2),
                width: imageSize.width,
                height: imageSize.height)
        }
    }

    struct K {
        static let textImageGap: CGFloat = 5
    }

}

Subclassing and over-riding layoutSubviews is probably your best way to go.子类化和覆盖 layoutSubviews 可能是您最好的方法。

Referenced from: iPhone UIButton - image position引用自: iPhone UIButton - 图像位置

Solutions mentioned here stopped working, once I enabled Auto Layout .一旦我启用了Auto Layout ,这里提到的解决方案就停止工作了。 I had to come up with my own:我不得不想出我自己的:

Subclass UIButton and override layoutSubviews method:子类化 UIButton 并覆盖layoutSubviews方法:

//
//  MIThemeButtonImageAtRight.m
//  Created by Lukasz Margielewski on 7/9/13.
//

#import "MIThemeButtonImageAtRight.h"

static CGRect CGRectByApplyingUIEdgeInsets(CGRect frame, UIEdgeInsets insets);

@implementation MIThemeButtonImageAtRight

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGRect contentFrame = CGRectByApplyingUIEdgeInsets(self.bounds, self.contentEdgeInsets);

    CGRect frameIcon = self.imageView.frame;
    CGRect frameText = self.titleLabel.frame;

    frameText.origin.x = CGRectGetMinX(contentFrame) + self.titleEdgeInsets.left;
    frameIcon.origin.x = CGRectGetMaxX(contentFrame) - CGRectGetWidth(frameIcon);

    self.imageView.frame = frameIcon;
    self.titleLabel.frame = frameText;
}

@end

static CGRect CGRectByApplyingUIEdgeInsets(CGRect frame, UIEdgeInsets insets){

    CGRect f = frame;

    f.origin.x += insets.left;
    f.size.width -= (insets.left + insets.right);
    f.origin.y += (insets.top);
    f.size.height -= (insets.top + insets.bottom);

    return f;

}

Result:结果:

在此处输入图片说明

swift 3.0 Migration solution given by jasongregori jasongregori提供的swift 3.0迁移解决方案

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
        }

要在 UIButton 中右对齐图像,请尝试以下代码

btn.contentHorizontalAlignment = .right

Xcode 11.4 Swift 5.2 Xcode 11.4 斯威夫特 5.2

For anyone trying to mirror the Back button style with the chevron like this:对于任何试图用人字形镜像后退按钮样式的人,如下所示:

在此处输入图片说明

import UIKit

class NextBarButton: UIBarButtonItem {

    convenience init(target: Any, selector: Selector) {

        // Create UIButton
        let button = UIButton(frame: .zero)

        // Set Title
        button.setTitle("Next", for: .normal)
        button.setTitleColor(.systemBlue, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 17)

        // Configure Symbol
        let config = UIImage.SymbolConfiguration(pointSize: 19.0, weight: .semibold, scale: .large)
        let image = UIImage(systemName: "chevron.right", withConfiguration: config)
        button.setImage(image, for: .normal)

        // Add Target
        button.addTarget(target, action: selector, for: .touchUpInside)

        // Put the Image on the right hand side of the button
        // Credit to liau-jian-jie for this part
        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)

        // Customise spacing to match system Back button
        button.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: -18.0, bottom: 0.0, right: 0.0)
        button.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -12.0, bottom: 0.0, right: 0.0)

        self.init(customView: button)
    }
}

Implementation:执行:

override func viewDidLoad() {
    super.viewDidLoad()
    let nextButton = NextBarButton(target: self, selector: #selector(nextTapped))
    navigationItem.rightBarButtonItem = nextButton
}

@objc func nextTapped() {
    // your code
}

If you want string to be on the left and image on the right, this should be fine (Swift 5)如果你想让字符串在左边,图像在右边,这应该没问题(Swift 5)

/// [ String ------------------ Image ] Style Custom Button
/// For use, just define 'Title Text' and 'Image' on ib / source with setting the class 'DistantTextImageButton'.

class DistantTextImageButton: UIButton {
    override func layoutSubviews() {
        super.layoutSubviews()
        self.semanticContentAttribute = .forceRightToLeft
        self.contentHorizontalAlignment = .left

        guard let imageView = imageView,
              let title = title(for: .normal),
              let font = titleLabel?.font else { return }
       
        imageEdgeInsets = UIEdgeInsets(top: 0, left: bounds.width - imageView.bounds.width - title.textSizeWithFont(font).width, bottom: 0, right: 0)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }
}

extension String {
    func textSizeWithFont(_ font: UIFont) -> CGSize {
        return self.size(withAttributes: [.font: font])
    }
}

Swift 3:斯威夫特 3:

open override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
    var frame = super.imageRect(forContentRect: contentRect)
    let  imageWidth = frame.size.width
    var titleRect = CGRect.zero
    titleRect.size = self.title(for: self.state)!.size(attributes: [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
}

open override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
    var frame = super.titleRect(forContentRect: contentRect)
    if let imageWidth = self.image(for: self.state)?.size.width {
        frame.origin.x = (self.frame.size.width - (frame.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    }
    return frame
}

How about Constraints?约束呢? Unlike semanticContentAttribute, they don't change semantics.与semanticContentAttribute 不同,它们不会改变语义。 Something like this perhaps:可能是这样的:

 button.rightAnchorconstraint(equalTo: button.rightAnchor).isActive = true

or in Objective-C:或在 Objective-C 中:

[button.imageView.rightAnchor constraintEqualToAnchor:button.rightAnchor].isActive = YES;

Caveats: Untested, iOS 9+注意事项:未经测试,iOS 9+

After trying multiple solutions from around the internet, I was not achieving the exact requirement.在尝试了互联网上的多种解决方案后,我没有达到确切的要求。 So I ended up writing custom utility code.所以我最终编写了自定义实用程序代码。 Posting to help someone in future.发布以帮助将来的某人。 Tested on swift 4.2在 swift 4.2 上测试

// This function should be called in/after viewDidAppear to let view render
    func addArrowImageToButton(button: UIButton, arrowImage:UIImage = #imageLiteral(resourceName: "my_image_name") ) {
        let btnSize:CGFloat = 32
        let imageView = UIImageView(image: arrowImage)
        let btnFrame = button.frame
        imageView.frame = CGRect(x: btnFrame.width-btnSize-8, y: btnFrame.height/2 - btnSize/2, width: btnSize, height: btnSize)
        button.addSubview(imageView)
        //Imageview on Top of View
        button.bringSubviewToFront(imageView)
    }

for this issue you can create UIView inside "label with UIImage view" and set UIView class as a UIControl and create IBAction as tuch up in side对于这个问题,您可以在“带有 UIImage 视图的标签”中创建 UIView 并将 UIView 类设置为 UIControl 并在侧边创建 IBAction

在此处输入图片说明

Swift 4 & 5斯威夫特 4 & 5

Change the direction of UIButton image (RTL and LTR)改变 UIButton 图像的方向(RTL 和 LTR)

extension UIButton {
    func changeDirection(){
       isArabic ? (self.contentHorizontalAlignment = .right) : (self.contentHorizontalAlignment = .left)
        // left-right margin 
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    }
}

I don't want to use a subview if I can avoid it.如果可以避免,我不想使用子视图。 I want a UIButton with a background image, text, and an image in it.我想要一个带有背景图像,文本和图像的UIButton Right now, when I do that, the image is on the left side of the text.现在,当我这样做时,图像位于文本的左侧。 The background image, text, and image all have different highlight states.背景图像,文本和图像均具有不同的突出显示状态。

Finally I got the perfect result what I want.最后我得到了我想要的完美结果。

Here is my code.这是我的代码。

self.semanticContentAttribute = .forceRightToLeft
self.contentHorizontalAlignment = .left

self.imageView?.translatesAutoresizingMaskIntoConstraints = false
self.imageView?.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
self.imageView?.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0.0).isActive = true

This code makes right text/left image button without any padding.此代码使右文本/左图像按钮没有任何填充。

iOS 15 brought an update where you can now handle image placements in buttons in a simpler non messier way, ie. iOS 15 带来了一个更新,您现在可以以更简单的非混乱方式处理按钮中的图像放置,即。 without insets.没有插图。

In XIB/Storyboards:在 XIB/故事板中: 在编辑器中修改按钮图像放置 Simply set the button 'placement' property to leading/training/top/bottom after adding an image property to button.将图像属性添加到按钮后,只需将按钮的“放置”属性设置为领先/训练/顶部/底部。 Since it's leading/training, there is an added advantage of it supporting RTL由于它是领先的/培训的,因此它支持 RTL 有一个额外的优势

**In code (Programmatically): ** Use Button Configuration property programmatically **在代码中(以编程方式):** 以编程方式使用按钮配置属性按钮配置,以编程方式

This is not a backward compatible feature, and will work only in iOS15+ as was demonstrated in WWDC '21 - https://developer.apple.com/videos/play/wwdc2021/10064/?time=236这不是向后兼容的功能,只能在 iOS15+ 中工作,如 WWDC '21 - https://developer.apple.com/videos/play/wwdc2021/10064/?time=236 中所示

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

Thanks to Vitaliy Gozhenko 感谢Vitaliy Gozhenko

I just want to add that you can add IB_DESIGNABLE before your button @interface and set your button class in storyborad. 我只想补充一下,您可以在按钮@interface之前添加IB_DESIGNABLE,并在storyborad中设置按钮类。 Then you can watch it layout in real time without app launch just at interface building stage 然后,您可以实时查看其布局,而无需在界面构建阶段启动应用程序

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM