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)
Vic*_*ius 232
更新XCODE 9(通过Interface Builder)
Interface Builder提供了一种更简单的方法.选择UIButton并在View Utilities中选择此选项:
而已!好又简单!
可选 - 第2步:
如果要调整图像和标题之间的间距,可以在此处更改图像插入:
希望有所帮助!
Ben*_*min 221
尽管一些建议的答案非常有创意且极其聪明,但最简单的解决方案如下:
button.semanticContentAttribute = UIApplication.shared
.userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft
Run Code Online (Sandbox Code Playgroud)
就如此容易.作为奖励,图像将位于从右到左区域的左侧.
编辑:由于问题已被问过几次,这是iOS 9 +.
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)
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)
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)
bar*_*dog 59
截至2016年1月,所有这些答案都是不必要的.在Interface Builder中,将View Semantic设置为Force Right-to-Left,或者如果您更喜欢以编程方式,semanticContentAttribute = .forceRightToLeft这将导致图像显示在文本的右侧.
Gen*_*kin 52
在界面构建器中,您可以为UIButton配置选项Edge Insets,分别为三个部分:内容,图像,标题

Xcode 8:
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
如果需要在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)
自己做。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 设计
我的意思是,我认为这里最简单的解决方案只是告诉按钮水平布局“填充”按钮的宽度,而不是像.left您最初想到的那样对齐:
contentHorizontalAlignment = .fill
Run Code Online (Sandbox Code Playgroud)
应该在这里解决问题。只要确保你告诉你的按钮有一个尾随图像位置:configuration.imagePlacement = .trailing,你应该得到以下结果:
只需将您发送configuration.contentInsets到您喜欢的任何位置即可为按钮提供一些美观的填充。
这是UIButton中心对齐内容的解决方案.此代码使图像右对齐,允许使用imageEdgeInsets和titleEdgeInsets进行宝贵的定位.
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)
由于转换解决方案在 iOS 11 中不起作用,我决定编写一种新方法。
调整按钮semanticContentAttribute为我们提供了很好的右侧图像,而无需在文本更改时重新布局。因此,它是理想的解决方案。但是我仍然需要 RTL 支持。应用程序无法在同一会话中更改其布局方向这一事实很容易解决此问题。
话虽如此,这很简单。
extension UIButton {
func alignImageRight() {
if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
semanticContentAttribute = .forceRightToLeft
}
else {
semanticContentAttribute = .forceLeftToRight
}
}
}
Run Code Online (Sandbox Code Playgroud)
延伸方式
使用扩展名在右侧使用自定义偏移设置图像
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)
| 归档时间: |
|
| 查看次数: |
151459 次 |
| 最近记录: |