1. ホーム
  2. ios

[解決済み] UIButton: imageEdgeInsets と titleEdgeInsets を使って、画像とテキストを中央揃えにする方法は?

2022-05-04 05:02:03

質問

ボタンに画像だけを配置し、imageEdgeInsetsをより上側に設定すると、画像は中央に配置され、すべてが期待通りに動作するようになりました。

[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];

ボタンにテキストのみを配置し、titleEdgeInsetsをもっと下に設定すると、テキストは中央のまま、すべてが期待通りに動作します。

[button setTitle:title forState:UIControlStateNormal];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];

しかし、4行を並べるとテキストが画像と干渉してしまい、どちらもセンター揃えが崩れてしまいました。

私の画像はすべて幅が30ピクセルで、setTitleEdgeInsetsのUIEdgeInsetMakeの左パラメータに30を入れると、テキストは再び中央に配置されます。問題は、button.titleLabelのサイズに依存しているように見えるので、画像が中央に配置されないことです。ボタンのサイズ、画像のサイズ、titleLabelのサイズで何度も計算してみましたが、両方とも完全に中央に配置されたことはありません。

どなたか同じ悩みをお持ちの方はいらっしゃいませんか?

解決方法は?

参考までに、魔法の数字を使わずに画像をテキストの中央に配置する一般的な方法を紹介します。 以下のコードは古いので、おそらく以下の更新されたバージョンのいずれかを使用することに注意してください。 :

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and push it right so it appears centered
//  above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

次のバージョンは、サポートに関する変更を含んでいます。 iOS 7+ 以下のコメントで推奨されているものです。私自身はこのコードをテストしていないので、どの程度うまく動作するか、また以前のバージョンのiOSで使用した場合に壊れるかどうかについては、わかりません。

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and push it right so it appears centered
//  above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);

Swift 5.0 バージョン

extension UIButton {
  func alignVertical(spacing: CGFloat = 6.0) {
    guard let imageSize = imageView?.image?.size,
      let text = titleLabel?.text,
      let font = titleLabel?.font
    else { return }

    titleEdgeInsets = UIEdgeInsets(
      top: 0.0,
      left: -imageSize.width,
      bottom: -(imageSize.height + spacing),
      right: 0.0
    )

    let titleSize = text.size(withAttributes: [.font: font])
    imageEdgeInsets = UIEdgeInsets(
      top: -(titleSize.height + spacing),
      left: 0.0,
      bottom: 0.0,
      right: -titleSize.width
    )

    let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
    contentEdgeInsets = UIEdgeInsets(
      top: edgeOffset,
      left: 0.0,
      bottom: edgeOffset,
      right: 0.0
    )
  }
}