右揃えに関する記事を見たことがありますが、左揃えが機能しません。左の画像と中央のタイトル/テキストで、ボタンが画面の幅を占めるようにします。
これは機能しません(少なくとも確実に):
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);
このソリューションはSwift 3で機能し、元のコンテンツと画像のエッジインセットを尊重しながら、タイトルラベルを常に使用可能なスペースの中央に配置するため、マージンの調整がはるかに容易になります。
titleRect(forContentRect:)
メソッドをオーバーライドし、正しいフレームを返します。
@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
を使用するため、iOS 9以降が必要です。
最後に、UIEdgeInsetsMakeを使用してこれを行いました。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];
出力は次のようになります。
InSwift:
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)
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以降、ナビゲーションbarは自動レイアウトに続くため、UIBarButtonItem
に幅/高さの制約を追加する必要があります。ナビゲーションバーでの使用については、Apple推奨される@ 2xおよび@ 3xの画像サイズ(50x50、75x75)に準拠し、iPhone 6、7、8、6sでのアクセシビリティを向上させるようにしてください。 7s、8s、PlusバリアントおよびiPhone x UIBarButton
の幅と高さは、高さ-25および幅-55(またはアプリが必要とするものであれば、これらの数値はほとんどの場合に機能する基本的な数値です) )。
[〜#〜] update [〜#〜]:In 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
}
}
ボタンを作成し、テキストの配置を中央に設定してから、次を追加します。
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];
私が思うに、良い解決策は、インセットのハードコードされた値なしで、どんなテキストにも役立つに違いありません(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];
うまく動作せず、1ステップで3〜4ポイントのフォントサイズが小さくなるように見えるので、それほど長くない行の一部が必要以上に小さくなります。
このコードにより、ボタンのタイトルスペースにテキストを正確に中央に配置できます。
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)
出来上がり!
これは、画像の幅とタイトルの長さが異なるいくつかのボタンで、私にとってうまく機能します:
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)
}
}
上記のほとんどすべてのソリューションを試してみましたが、期待どおりに機能しませんでした(タイトルとイメージ幅が異なる2つのボタンがありました)。だから、私は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()
運のないほとんどの答えを試してみました。ほとんどの場合、青い画像が表示されるか、タイトルが中央にありませんでした。いくつかの回答のコードを使用してこの拡張機能を作成しましたが、これは魅力のように機能します。
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)
}
}
それが一部に役立つことを願っています!
私はこの答えがちょっと遅いことを知っています。しかし、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
}
}
ここには、アイコンを左に設定することに焦点を当てた多くの解決策があります。 UIImageViewを追加し、ボタンと画像の左側を揃えて中央揃えする方が簡単だと思います。その後、オフセットを少し再生して、見た目を良くすることができます。
Interface Builderにコードはありません。
1)button.frame = self.view.bounds;
2)負の値を持つsetImageEdgeInsets
は、ボタンが画面いっぱいになったときの狂気です。ここでやろうとしていることを再考しますか?
3)UITextAlignmentCenter
はNSTextAlignmentCenter
になりました
4)button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
Swift-
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)
これにより、画像は左境界線からのパディングで左揃えになります。
このコードにより、ボタンの画像が左揃えになり、タイトルラベルがボタンの中央に移動します。 bはボタンです:)
b.contentHorizontalAlignment = .Left
let left = (b.frameWidth() - b.titleLabel!.frameWidth()) / 2 - CGRectGetMaxX(b.imageView!.frame)
b.titleEdgeInsets = UIEdgeInsetsMake(0, left, 0, 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,,
}
おかげで、
1つの秘isは次のとおりです。
titleRectForContentRect
をオーバーライドして、ボタンのtitleLabel
のframe
をボタンの境界に等しくするtitleLabel
のtextAlignment
を.Center
に設定しますimageRectForContentRect
をオーバーライドして、ボタンのimageView
のOrigin.x
を指定します
import UIKit
class ButtonWithLeftAlignedImageAndCenteredText: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel?.textAlignment = .Center
}
override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
var imageFrame = super.imageRectForContentRect(contentRect)
imageFrame.Origin.x = 20 //offset from left Edge
return imageFrame
}
override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
var titleFrame = super.titleRectForContentRect(contentRect)
titleFrame = self.bounds
return titleFrame
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
次の拡張機能は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)
}
このソリューションは、拡張機能を使用して適用できます。サブクラス化の必要はありません。
警告:これは、テキスト/画像が更新されるたびに呼び出す必要があります。
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)