76

右揃えに関する投稿を見たことがありますが、左揃えが機能しません。ボタンが画面の幅を占めるようにし、画像を左側に、タイトル/テキストを中央に配置します。

これは機能しません(少なくとも確実に):

    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);
4

26 に答える 26

75

このソリューションは 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 以降が必要です。

于 2017-01-10T17:41:09.583 に答える
9
[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];

うまくいかない場合はお知らせください。

私の出力ここに画像の説明を入力

于 2016-07-08T12:22:01.553 に答える
9

私が思うに、良い解決策は、インセットのハードコードされた値なしで、どのテキストにも役立つはずです (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ポイントのフォントサイズが1ステップで小さくなるように見えるため、それほど長くない行が必要以上に小さくなりすぎます.

このコードにより、ボタン タイトル スペースのテキストを正確に中央に配置できます。

于 2013-09-13T10:04:15.000 に答える
3

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)

これにより、画像が左の境界線からのパディングで左揃えになります。

于 2016-05-11T10:38:44.657 に答える
2

1)button.frame = self.view.bounds;

2)setImageEdgeInsets負の値を使用すると、ボタンが画面いっぱいに表示されたときに狂気になります。ここで何をしようとしているのか考え直してください。

3)UITextAlignmentCenter今はNSTextAlignmentCenter

4)button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

于 2013-01-17T10:22:57.423 に答える
2

私はこの答えがちょっと遅いことを知っています。しかし、中央揃えのテキストを持つ UIButton の左側に、UIImageView を使用して画像を追加したい人のための非常にシンプルなソリューションがあります。すべてプログラムで

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
    }

}
于 2017-05-01T15:50:16.237 に答える
1

1つのトリックは次のとおりです。

  1. ボタンの をボタンの境界と等しくするためにオーバーライドtitleRectForContentRectしますtitleLabelframe
  2. を に設定しtitleLabelますtextAlignment.Center
  3. ボタンのimageRectForContentRect_origin.ximageView

    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")
        }
    }
    
于 2016-02-15T17:36:19.480 に答える
1

このソリューションは、拡張機能を使用して適用できます。サブクラス化の必要はありません。

警告: テキスト/画像が更新されるたびにこれを呼び出す必要があります。

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)
于 2018-06-05T19:51:31.247 に答える
-2

この問題に適切に対処するには、カスタム UIButton サブクラスを作成するのが最善の方法かもしれません。Apple が設定を「リセット」している可能性があります。

于 2012-06-08T19:22:02.407 に答える