如果可以避免,我不想使用子视图。我想要一个带有背景图片、文本和图像的UIButton
。目前,当我这样做时,图像在文本的左侧。背景图片、文本和图像都有不同的高亮状态。
如果可以避免,我不想使用子视图。我想要一个带有背景图片、文本和图像的UIButton
。目前,当我这样做时,图像在文本的左侧。背景图片、文本和图像都有不同的高亮状态。
最简单的解决方案:
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)
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及以上版本,Swift:(推荐)
button.semanticContentAttribute = .forceRightToLeft
button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);
。这是在Xamarin中,但应该很容易转换到Swift/Obj-C。 - Lee RichardsonsemanticContentAttribute
的致命缺陷在于它会破坏语音导航。语音导航使用语义内容属性来确定通过元素的导航方向,改变语义意味着用户到达按钮后,他们的 VO 导航将被翻转并回到他们刚才访问的元素而不是下一个元素。请注意,这句话中的 WILL 表示强调,表示“一定会”,需要保留其强调的意义。 - timzilla尽管有些提出的答案非常有创意和极为聪明,但最简单的解决方案如下:
button.semanticContentAttribute = UIApplication.shared
.userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft
就是这么简单。作为额外的奖励,在从右到左的语言环境中,该图像将位于左侧。
编辑:由于这个问题已经被问了几次,这是 iOS 9+。
semanticContentAttribute
只是一种hack或解决方法,而不是真正的解决方案。 - ZoltánUIUserInterfaceLayoutDirection.rightToLeft
文档说明:
“从右到左的布局方向。当本地化为阿拉伯语或希伯来语等需要用户界面布局原点在坐标系右边缘的情况时,此值是合适的。”UIButton具有一个imageEdgeInsets
属性,可以在代码或IB中设置。它是专门用于重新定位按钮图像的正确方式。 - Alex Chase不必要完全地对UIButton进行子类化。相反,您可以为图像插入设置较高的左插入值,并为标题设置较小的右插入值。类似这样:
子类化 UIButton 是完全不必要的。相反,您可以为图像插入设置较高的左插入值,并将标题的右插入设置为较小的值。类似如下:
button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);
我要感谢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
buttonWithType
如果您子类化了UIButton,则此方法不会返回您的子类的实例。如果要创建特定子类的实例,则必须直接分配/初始化按钮。backgroundRectForBounds
提供自定义背景装饰的子类可以重写此方法并返回修改后的边界矩形,以防止按钮绘制在任何自定义内容上方。两者都没有提到这些特定方法,但我认为它们不介意子类。 - christophercottonframe.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;
它适用于 UIControlContentHorizontalAlignmentCenter
和其他模式... - k06a当标题更改时,只需更新插图。您需要在另一侧使用相等且相反的插入来补偿插入。
[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);
[thebutton.titleLabel sizeToFit];
。如果您尚未触发布局,则宽度可能为零。图像大小也是如此(只需使用UIImage.size而不是imageView大小)。 - scosmantitleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;
(或者如果您担心按钮框架尚未建立,请在高度上也使用 CGFLOAT_MAX)和 imageWidth = self.currentImage.size.width;
。 - Dave GoldmanUITableViewCell
子类的layoutSubviews
中,但它工作得很好。谢谢! - RyanG截止到2016年1月,这些回答都已经不再需要。在界面构建器中,将“视图语义”设置为Force Right-to-Left
,或者如果您更喜欢编程方式,则为semanticContentAttribute = .forceRightToLeft
。这将导致图像出现在文本的右侧。
UIBarButtonItem(customView: button)
,那么它将无法工作,但是如果您在某些空视图中包装按钮,则可以正常工作。 - tt.Kilewextension 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)
])
}
}
更新: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
}
}
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
}
}
@IBDesignable
到类中并查看它翻转。 - James Toomey