我见过有关正确对齐的帖子,但我无法让左对齐工作。我希望按钮占据屏幕的宽度,左边的图像和中间的标题/文字。
这不起作用(至少可靠):
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setImageEdgeInsets:UIEdgeInsetsMake(0, -60.0, 0, 0)];
button.frame = CGRectMake((self.view.frame.size.width - w ) / 2, self.view.frame.size.height - 140.0, self.view.frame.size.width - 10.0, 40.0);
答案 0 :(得分:50)
此解决方案适用于Swift 3并尊重原始内容和图像边缘插入,同时保持标题标签始终位于可用空间的中心,这样可以更轻松地调整边距。
它会覆盖@IBDesignable
class LeftAlignedIconButton: UIButton {
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
let titleRect = super.titleRect(forContentRect: contentRect)
let imageSize = currentImage?.size ?? .zero
let availableWidth = contentRect.width - imageEdgeInsets.right - imageSize.width - titleRect.width
return titleRect.offsetBy(dx: round(availableWidth / 2), dy: 0)
}
}
方法并返回正确的框架:
layoutSubviews
以下内容:
会导致:
弃用之前的回答
这适用于大多数情况,但有些布局会导致@IBDesignable
class LeftAlignedIconButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
contentHorizontalAlignment = .left
let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
}
}
以无限循环递归调用自身,因此谨慎使用。
@IBDesignable
class RightAlignedIconButton: UIButton {
override func layoutSubviews() {
super.layoutSubviews()
semanticContentAttribute = .forceRightToLeft
contentHorizontalAlignment = .right
let availableSpace = UIEdgeInsetsInsetRect(bounds, contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
}
}
此代码会执行相同操作,但将图标与右边缘对齐:
semanticContentAttribute
正确的分配版本使用$a = array('');
$a = array_values($a);
print_r($a);
,因此需要iOS 9 +。
答案 1 :(得分:44)
在我的最后,我使用UIEdgeInsetsMake做了这个,计算左角到达中心。我不确定是否有什么东西可以使文本在中心对齐,但这对我有用。确保通过计算宽度将左角设置到所需位置。例如UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f)
UIButton *scanBarCodeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
scanBarCodeButton.frame = CGRectMake(center, 10.0f, fieldWidth, 40.0f);
[scanBarCodeButton setImage:[UIImage imageNamed:@"BarCodeIcon.png"] forState:UIControlStateNormal];
[scanBarCodeButton setTitle:@"Scan the Barcode" forState:UIControlStateNormal];
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0f, 42.0f, 0.0f, 0.0f);
[scanBarCodeButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[scanBarCodeButton addTarget:self action:@selector(scanBarCode:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:scanBarCodeButton];
输出看起来像,
centered text with image http://i43.tinypic.com/33mbxxi.png
在 Swift :
var scanBarCodeButton: UIButton = UIButton(type: .roundedRect)
scanBarCodeButton.frame = CGRectMake(center, 10.0, fieldWidth, 40.0)
scanBarCodeButton.setImage(UIImage(named: "BarCodeIcon.png"), for: UIControlStateNormal)
scanBarCodeButton.setTitle("Scan the Barcode", for: UIControlStateNormal)
scanBarCodeButton.titleEdgeInsets = UIEdgeInsetsMake(0.0, 42.0, 0.0, 0.0)
scanBarCodeButton.contentHorizontalAlignment = .left
scanBarCodeButton.addTarget(self, action: "scanBarCode:", for: UIControlEventTouchUpInside)
self.view.addSubview(scanBarCodeButton)
答案 2 :(得分:10)
对于Swift 4.0,这是一个有效的扩展 -
extension UIButton {
func leftImage(image: UIImage, renderMode: UIImageRenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
self.contentHorizontalAlignment = .left
self.imageView?.contentMode = .scaleAspectFit
}
func rightImage(image: UIImage, renderMode: UIImageRenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
self.contentHorizontalAlignment = .right
self.imageView?.contentMode = .scaleAspectFit
}
}
用法:
myButton.rightImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
myButton.leftImage(image: UIImage(named: "image_name")!, renderMode: .alwaysOriginal)
renderMode
可以是.alwaysTemplate
或.alwaysOriginal
。此外,myButton
应为custom
类型UIButton
。
这个扩展程序的leftImage
和rightImage
也可以UIButton
UIBarButtonItem
用于UINavigationBar
(注意:从iOS 11开始,导航栏如下autolayout所以你需要为UIBarButtonItem
添加宽度/高度约束。要在导航栏上使用,请确保遵循Apple推荐的@ 2x和@ 3x图像尺寸(即50x50,75x75),并在iPhone 6,7,8,6s,7s,8s,Plus版本和iPhone上具有更好的可访问性x UIBarButton
的宽度和高度可以是高度 - 25和宽度 - 55(或者您的应用需要的任何数字,这些数字是一些基本数字,适用于大多数情况)。
更新:在Swift 4.2中,UIImageRenderingMode
已重命名为UIImage.RenderingMode
extension UIButton {
func leftImage(image: UIImage, renderMode: UIImage.RenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width / 2)
self.contentHorizontalAlignment = .left
self.imageView?.contentMode = .scaleAspectFit
}
func rightImage(image: UIImage, renderMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left:image.size.width / 2, bottom: 0, right: 0)
self.contentHorizontalAlignment = .right
self.imageView?.contentMode = .scaleAspectFit
}
}
答案 3 :(得分:7)
创建按钮并将文本对齐方式设置为居中,然后添加:
UIImage *image = [UIImage imageNamed:@"..."];
CGSize imageSize = image.size;
CGFloat offsetY = floor((self.layer.bounds.size.height - imageSize.height) / 2.0);
CALayer *imageLayer = [CALayer layer];
imageLayer.contents = (__bridge id) image.CGImage;
imageLayer.contentsGravity = kCAGravityBottom;
imageLayer.contentsScale = [UIScreen mainScreen].scale;
imageLayer.frame = CGRectMake(offsetY, offsetY, imageSize.width, imageSize.height);
[self.layer addSublayer:imageLayer];
答案 4 :(得分:7)
正如我所想,对于任何文本而言,良好的解决方案必须是有用的,没有用于插入的硬编码值(它是关于toytoy提供的解决方案)。我使用类似的代码:
NSString *sometitle = @"blabla button title";
NSString *someimage = @"blablaimage";
UIImage *image = [[UIImage imageNamed:someimage];
int buttonWidth = A;
int buttonHeight = B;
int imageWidth =image.size.width;
int imageHeight = image.size.height;
int titleWidth = buttonWidth - imageWidth;
// create button and set image and title
buttonView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, buttonWidth, buttonHeight)];
[buttonView setImage:image forState:UIControlStateNormal];
[buttonView setTitle:sometitle forState:UIControlStateNormal];
// make button all content to be left aligned
[buttonView setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
// set title font
[buttonView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:14]];
// calculate font text width with selected font
CGSize stringBoundingBox = [number sizeWithFont:[buttonView.titleLabel font]];
// make title inset with some value from left
// it place the title right on the center of space for the title
int titleLeft = (titleWidth - stringBoundingBox.width) / 2;
[buttonView setTitleEdgeInsets:UIEdgeInsetsMake(0, titleLeft, 0, 0)];
在使用stringBoundingBox init的字符串之后,我还添加了一些这样的字符串:
if (stringBoundingBox.width > titleWidth)
{
[_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:13]];
stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
if (stringBoundingBox.width > titleWidth)
{
[_backgroundView.titleLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:12]];
stringBoundingBox = [number sizeWithFont:[_backgroundView.titleLabel font]];
}
它允许我通过选择一些较小的字体来设置比可用空间更长的标题。我这样做是因为另一种方式:
[buttonView.titleLabel setAdjustsFontSizeToFitWidth:YES];
工作效果不是很好,看起来它的字体大小一步缩小了3-4个点,所以有些不那么长的线条变得太小了。
此代码允许我们将按钮标题空间中的任何文本正好放在中心。
答案 5 :(得分:6)
[self.button setImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
[self.button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, self.button.center.x/2 , 0.0, 0.0)];
[self.button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
如果它不起作用,请告诉我。
答案 6 :(得分:5)
我写了一个UIButton扩展名。
extension UIButton {
/// Add image on left view
func leftImage(image: UIImage) {
self.setImage(image, for: .normal)
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: image.size.width)
}
}
你可以这样使用:
yourButton.leftImage(image: yourImage)
瞧!
答案 7 :(得分:4)
这适用于我,对于几个按钮,具有不同的图像宽度和不同的标题长度:
子类UIButton
,并添加以下方法:
override func layoutSubviews() {
super.layoutSubviews()
if let image = imageView?.image {
let margin = 30 - image.size.width / 2
let titleRect = titleRectForContentRect(bounds)
let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2
contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width - image.size.width - margin) / 2, 0, 0)
}
}
答案 8 :(得分:2)
尝试大多数答案都没有运气。我大多数时候都得到蓝色图像,或者标题不居中。使用了一些答案中的代码并编写了此扩展程序,其工作原理很吸引人。
Swift 4.2:
import UIKit
extension UIButton {
func moveImageLeftTextCenter(image : UIImage, imagePadding: CGFloat, renderingMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderingMode), for: .normal)
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .left
let imageLeft = imagePadding - imageViewWidth / 2
let titleLeft = (bounds.width - titleLabelWidth) / 2 - imageViewWidth
imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imageLeft, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: titleLeft , bottom: 0.0, right: 0.0)
}
}
希望对某些人有帮助!
答案 9 :(得分:1)
1)button.frame = self.view.bounds;
2)setImageEdgeInsets
具有负值,当您的按钮填满屏幕时,是疯狂的。重新考虑你在这里想做什么?
3)UITextAlignmentCenter
现在是NSTextAlignmentCenter
4)button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
答案 10 :(得分:1)
我的 SWIFT 5.2 解决方案。
您必须继承UIButton类。无需像其他答案中那样更改内容的水平对齐方式,只需将其保持在“中心”(.center)即可。标题将自动居中,而imageRect()的覆盖将解决图像问题。
您要做的第一件事是在故事板的“身份检查器”部分中将CustomButton类分配给您的按钮。 然后,您可以在“属性检查器”部分将“ alignImageToLeft”切换为“开”或“关”(默认为“关”)。
class CustomButton : UIButton {
@IBInspectable var alignImageToLeft : Bool = false
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
if(alignImageToLeft){
let imageRect = super.imageRect(forContentRect: contentRect)
let offset = contentRect.minX - imageRect.minX
return imageRect.offsetBy(dx: offset, dy: 0.0)
}
return super.imageRect(forContentRect: contentRect)
}
}
答案 11 :(得分:1)
我知道这个答案有点晚了。 但是对于想要使用UIImageView在具有居中文本的UIButton的左侧添加图像的人来说,我有一个非常简单的解决方案。全部以编程方式
class RandomVC: UIViewController{
var imageDemo: UIImageView = {
let img = UIImageView()
img.translatesAutoresizingMaskIntoConstraints = false
img.image = UIImage(named: "someImgFromAssets")
return img
}()
lazy var someButton: UIButton = { //lazy var: so button can have access to self class
let button = UIButton(type: .system)
button.setTitle("This is your title", for: UIControlState.normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(UIColor.white, for: UIControlState.normal)
button.addTarget(self, action: #selector(handleButtonClick), for: .touchUpInside) //make sure you write function "handleButtonClick" inside your class
button.titleLabel?.textAlignment = .center
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubView(someButton)
someButton.addSubview(imageDemo)
imageDemo.centerYAnchor.constraint(equalTo: someButton.centerYAnchor).isActive = true
imageDemo.leftAnchor.constraint(equalTo: someButton.leftAnchor, constant: 10).isActive = true
imageDemo.heightAnchor.constraint(equalToConstant: 25).isActive = true
imageDemo.widthAnchor.constraint(equalToConstant: 25).isActive = true
}
}
答案 12 :(得分:1)
我在swift中写了一个UIButton扩展 -
extension UIButton {
func setLeftImage(imageName:String, padding:CGFloat) {
//Set left image
let image = UIImage(named: imageName)
self.setImage(image, forState: .Normal)
//Calculate and set image inset to keep it left aligned
let imageWidth = image?.size.width
let textWidth = self.titleLabel?.intrinsicContentSize().width
let buttonWidth = CGRectGetWidth(self.bounds)
let padding:CGFloat = 30.0
let rightInset = buttonWidth - imageWidth! - textWidth! - padding
self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: rightInset)
}
}
我会以我想要的任何方式设置我的按钮文本样式,保持中心对齐。 然后我会在我的按钮上调用这个方法,如 -
myButton.setLeftImage("image_name", 30.0)
这会导致我的图像与左边框的某些填充对齐。
答案 13 :(得分:1)
我在这里看到很多解决方案,专注于将图标设置在左侧。我认为只需添加一个UIImageView,对齐按钮的左侧和图像,并将它们集中在一起就更容易了。然后你可以使用偏移量来使它看起来很漂亮。
没有代码,全部在Interface Builder中。
答案 14 :(得分:0)
此代码使您的按钮图像向左对齐,标题标签移动到按钮的中心。 b是按钮:)
new Parent(id,name)
答案 15 :(得分:0)
您可以使用以下代码在UIButton上左对齐图像: -
第1步:
//create your UIButton
UIButton *post_bNeeds_BTN= [UIButton buttonWithType:UIButtonTypeRoundedRect];
post_bNeeds_BTN.frame= CGRectMake(160 ,5 ,150 ,40);
[post_bNeeds_BTN addTarget:self action:@selector(post_Buying_Needs_BTN_Pressed:) forControlEvents:UIControlEventTouchUpInside];
[post_bNeeds_BTN setBackgroundColor:[UIColor colorWithRed:243/255.0 green:131/255.0 blue:26/255.0 alpha:1.0f]];//230
[self.view addSubview:post_bNeeds_BTN];
post_bNeeds_BTN.autoresizingMask= UIViewAutoresizingFlexibleWidth;
第2步:
//Add UIImageView on right side the button
UIImageView *bNeedsIVw= [[UIImageView alloc] initWithFrame:CGRectMake(5,5,30,30)];
bNeedsIVw.image= [UIImage imageNamed:@"postRequir_30.png"];
bNeedsIVw.image= [bNeedsIVw.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
bNeedsIVw.tintColor= [UIColor whiteColor];
[post_bNeeds_BTN addSubview:bNeedsIVw];
第3步:
//also set UILable on UIButton
UILabel *bNeedsLbl= [[UILabel alloc] initWithFrame:CGRectMake(40 ,0 ,post_Prod_BTN.frame.size.width-40 ,post_Prod_BTN.frame.size.height)];
bNeedsLbl.text= @"Requirements";
bNeedsLbl.font= [UIFont systemFontOfSize:16];
bNeedsLbl.textColor= [UIColor whiteColor];
bNeedsLbl.textAlignment= NSTextAlignmentLeft;
[post_bNeeds_BTN addSubview:bNeedsLbl];
第4步:
-(void)post_Buying_Needs_BTN_Pressed:(id)sender{
//write your code action here,,
}
感谢,
答案 16 :(得分:0)
我已经尝试了几乎所有上述解决方案,并且没有一个像我预期的那样工作(我有两个按钮,每个按钮具有不同的tittle和不同的图像宽度)。所以我为UIButton编写了自己的扩展,它可以完美地运行不同的图像宽度以及不同的标题。
extension UIButton {
func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .left
imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
}
}
用法:myButton.moveImageLeftTextCenter()
答案 17 :(得分:0)
一招是:
titleRectForContentRect
以使按钮的titleLabel
的{{1}}等于按钮的界限frame
的{{1}}设置为titleLabel
覆盖textAlignment
以指定按钮的.Center
imageRectForContentRect
origin.x
答案 18 :(得分:0)
可以使用扩展程序应用此解决方案。不需要子类化。
警告:每次更新文本/图像时都必须调用此方法。
let width = frame.width
guard let imageWidth = imageView?.frame.width, let labelWidth = titleLabel?.frame.width else {
return
}
titleEdgeInsets = UIEdgeInsets(top: 0, left: (width - labelWidth)/2.0 - imageWidth, bottom: 0, right: 0)
答案 19 :(得分:0)
以下扩展程序在Swift 4.2中对我有效
func leftImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode) {
self.setImage(image.withRenderingMode(renderMode), for: .normal)
contentHorizontalAlignment = .left
let availableSpace = bounds.inset(by: contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.right - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: availableWidth / 2, bottom: 0, right: 0)
imageEdgeInsets = UIEdgeInsets(top: 0, left: padding, bottom: 0, right: 0)
}
func rightImage(image: UIImage, padding: CGFloat, renderMode: UIImage.RenderingMode){
self.setImage(image.withRenderingMode(renderMode), for: .normal)
semanticContentAttribute = .forceRightToLeft
contentHorizontalAlignment = .right
let availableSpace = bounds.inset(by: contentEdgeInsets)
let availableWidth = availableSpace.width - imageEdgeInsets.left - (imageView?.frame.width ?? 0) - (titleLabel?.frame.width ?? 0)
titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: availableWidth / 2)
imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: padding)
}
答案 20 :(得分:0)
您可能会忘记UIEdgeInsets,而只是在UIButton子类中的layoutSubviews()中覆盖框架。
要使titleLable居中,只需将super.bounds.midX和titleLabel.frame.midX之间的差异添加到titleLabel框架的水平偏移量
override func layoutSubviews() {
super.layoutSubviews()
if let label = titleLabel {
label.frame = label.frame.offsetBy(dx: super.bounds.midX -
label.frame.midX , dy: 0)
}
// Available space to the left of the titleLabel is simply:
let leftAvailableWidth = label.frame.minX
imageView?.frame = CGRect(x: 0, y: 0, width: <Some width smaller than leftAvailableWidth>, height: super.bound.height)
}
答案 21 :(得分:-1)
迅速5: 您可以通过使用UIButton的自定义类来实现。
class CustomButton: UIButton {
var imageV = UIImageView()
var titleV = UILabel()
override func awakeFromNib() {
self.imageView?.isHidden = true
self.titleLabel?.isHidden = true
imageV.frame = CGRect(x: 0, y: 0, width: 40, height: self.bounds.height)
imageV.contentMode = .scaleAspectFit
titleV.frame = CGRect(x: 40, y: 0, width: self.bounds.width - 40, height: self.bounds.height)
titleV.font = self.titleLabel?.font
titleV.textAlignment = .center
self.addSubview(imageV)
self.addSubview(titleV)
imageV.image = self.imageView?.image; titleV.text = self.titleLabel?.text
imageV.translatesAutoresizingMaskIntoConstraints = false
imageV.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
imageV.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
imageV.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
imageV.trailingAnchor.constraint(equalTo: titleV.leadingAnchor, constant: 0).isActive = true
imageV.widthAnchor.constraint(equalToConstant: 40).isActive = true
titleV.translatesAutoresizingMaskIntoConstraints = false
titleV.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
titleV.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
titleV.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
}
}
然后您可以像这样设置图像和文本。
button.imageV.image = myImage
button.titleV.text = myText
结果
答案 22 :(得分:-1)
最好创建一个自定义UIButton子类,以更好的方式解决这个问题。 Apple可能正在“重置”您的设置。
答案 23 :(得分:-1)