iPhone UIButton - 图像位置

Pav*_*nko 113 iphone cocoa-touch uibutton ios imageedgeinsets

我有一个UIButton文本"探索应用程序"和UIImage(>)在Interface Builder它看起来像:

[ (>) Explore the app ]
Run Code Online (Sandbox Code Playgroud)

但我需要UIImage在文本之后放置:

[ Explore the app (>) ]
Run Code Online (Sandbox Code Playgroud)

我怎样才能UIImage向右移动?

Spl*_*lit 159

我对此的解决方案非常简单

[button sizeToFit];
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);
Run Code Online (Sandbox Code Playgroud)

  • 这很棒!很难理解边缘插入概念.知道为什么我们需要设置左右边缘插入?从理论上讲,如果我将标题向左移动而图像向右移动,那就足够了.为什么我需要设置左右两个? (4认同)
  • 我发现的最好的解决方案 (3认同)
  • 这个答案非常有效.接受的答案是正确的,并指向正确的API文档,但这是执行OP请求的复制和粘贴解决方案. (2认同)

Alv*_*ivi 122

iOS 9以后,似乎实现这一点的一种简单方法是强制视图的语义.

在此输入图像描述

或者以编程方式,使用:

button.semanticContentAttribute = .ForceRightToLeft
Run Code Online (Sandbox Code Playgroud)

  • 尽管我喜欢你的答案(+1),但我不想说这可能不是"正确"的方式,但这是最简单的方法之一. (4认同)
  • @SammanBikramThapa恕我直言,正确的方法是将UIButton子类化并覆盖layoutSubviews并尊重布局逻辑中的“ semanticContentAttribute”,而不是更改“ semanticContentAttribute”本身。(更改语义方法,不适用于国际化) (3认同)

Ste*_*eld 85

设置imageEdgeInsettitleEdgeInset移动图像中的组件.您还可以使用全尺寸的图形创建按钮,并将其用作按钮的背景图像(然后用于titleEdgeInsets移动标题).

  • 简单地设置insets而不是实现子类的代码要少得多.这是内容的重点.操纵子视图(你还没有创建)的框架感觉更像是一个黑客. (8认同)
  • @kimsnarf,真的吗?每当你对图像的大小或标题的长度进行微小的改变时,调整插图的工作量会少得多(并且*少*黑客)? (6认同)

Chr*_*les 54

Raymond W的答案最好.使用自定义layoutSubviews子类UIButton.非常简单,这是一个适用于我的layoutSubviews实现:

- (void)layoutSubviews
{
    // Allow default layout, then adjust image and label positions
    [super layoutSubviews];

    UIImageView *imageView = [self imageView];
    UILabel *label = [self titleLabel];

    CGRect imageFrame = imageView.frame;
    CGRect labelFrame = label.frame;

    labelFrame.origin.x = imageFrame.origin.x;
    imageFrame.origin.x = labelFrame.origin.x + CGRectGetWidth(labelFrame);

    imageView.frame = imageFrame;
    label.frame = labelFrame;
}
Run Code Online (Sandbox Code Playgroud)

  • 这种方式在你需要管理许多按钮的情况下更好,但我只需要改变一个按钮:) (2认同)
  • 如果按钮图像为零,则标签结果放错位置,可能是因为未插入UIImageView(在iOS6.0上测试).仅当imageView.image不为nil时才应考虑编辑帧. (2认同)
  • 我建议对此答案进行以下改进,以便两个视图保持居中:'CGFloat cumulativeWidth = CGRectGetWidth(imageFrame)+ CGRectGetWidth(labelFrame)+ 10; CGFloat excessWidth = CGRectGetWidth(self.bounds) - cumulativeWidth; labelFrame.origin.x = excessWidth/2; imageFrame.origin.x = CGRectGetMaxX(labelFrame)+ 10;' (2认同)

小智 30

子类化UIButton和重写layoutSubviews怎么样?

然后后处理self.imageView&的位置self.titleLabel

  • 这比使用手动调整插图正确放置所有内容的所有其他建议(如上所述)要容易得多. (4认同)

DrA*_*L3X 12

另一种简单的方法(仅限iOS 9)是将UIButton子类化为覆盖这两种方法

override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.titleRectForContentRect(contentRect)
    rect.origin.x = 0
    return rect
}

override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.imageRectForContentRect(contentRect)
    rect.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(rect)
    return rect
}
Run Code Online (Sandbox Code Playgroud)

contentEdgeInsets 已经考虑过使用super了.


小智 9

如果您的应用同时支持"从左到右"和"从右到左",则不能强制选择按钮"从右到左".

对我有用的解决方案是一个子类,可以添加到Storyboard中的按钮,并且可以很好地处理约束(在iOS 11中测试):

class ButtonWithImageAtEnd: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let imageView = imageView, let titleLabel = titleLabel {
            let padding: CGFloat = 15
            imageEdgeInsets = UIEdgeInsets(top: 5, left: titleLabel.frame.size.width+padding, bottom: 5, right: -titleLabel.frame.size.width-padding)
            titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageView.frame.width, bottom: 0, right: imageView.frame.width)
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

'padding'将是标题和图像之间的空间.

  • 当然 `.forceRightToLeft` 是一个选项!如果“UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft”,则只需使用相反的值(“.forceLeftToRight”)。 (2认同)

Chi*_*buZ 5

在Swift中:

override func layoutSubviews(){
    super.layoutSubviews()

    let inset: CGFloat = 5

    if var imageFrame = self.imageView?.frame,
       var labelFrame = self.titleLabel?.frame {

       let cumulativeWidth = imageFrame.width + labelFrame.width + inset
       let excessiveWidth = self.bounds.width - cumulativeWidth
       labelFrame.origin.x = excessiveWidth / 2
       imageFrame.origin.x = labelFrame.origin.x + labelFrame.width + inset

       self.imageView?.frame = imageFrame
       self.titleLabel?.frame = labelFrame  
    }
}
Run Code Online (Sandbox Code Playgroud)


Pav*_*nko 0

这是我自己的做法,(大约10年后)

  1. UIButton 的子类(Button,因为我们生活在 Swift 时代)
  2. 将图像和标签放入堆栈视图中。
class CustomButton: Button {

    var didLayout: Bool = false // The code must be called only once

    override func layoutSubviews() {
        super.layoutSubviews()
        if !didLayout, let imageView = imageView, let titleLabel = titleLabel {
            didLayout = true
            let stack = UIStackView(arrangedSubviews: [titleLabel, imageView])
            addSubview(stack)
            stack.edgesToSuperview() // I use TinyConstraints library. You could handle the constraints directly
            stack.axis = .horizontal
        }
    }
}
Run Code Online (Sandbox Code Playgroud)