web-dev-qa-db-ja.com

iPhone UIButton-画像の位置

「アプリを探す」というテキストとUIButton(>)を含むUIImageがありますInterface Builderでは、次のようになります。

[ (>) Explore the app ]

しかし、テキストの後にこのUIImageを配置する必要があります。

[ Explore the app (>) ]

UIImageを右に移動するにはどうすればよいですか?

111
Pavel Yakimenko

アプリが「左から右」と「右から左」の両方をサポートしている場合、ボタンに「右から左」を強制することはオプションではありません。

私のために働いたソリューションは、ストーリーボードのボタンに追加できるサブクラスであり、制約でうまく機能します(iOS 11でテスト済み)。

class ButtonWithImageAtEnd: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let imageView = imageView, let titleLabel = titleLabel {
            let padding: CGFloat = 15
            imageEdgeInsets = UIEdgeInsets(top: 5, left: titleLabel.frame.size.width+padding, bottom: 5, right: -titleLabel.frame.size.width-padding)
            titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageView.frame.width, bottom: 0, right: imageView.frame.width)
        }

    }

}

「パディング」とは、タイトルと画像の間のスペースです。

8
Luisma

これに対する私の解決策は非常に簡単です

[button sizeToFit];
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width);
159
Split

iOS 9以降では、これを実現する簡単な方法は、ビューのセマンティックを強制することです。

enter image description here

または、プログラムを使用して:

button.semanticContentAttribute = .ForceRightToLeft
118
Alvivi

imageEdgeInsettitleEdgeInsetを設定して、画像内でコンポーネントを移動します。フルサイズのグラフィックスを使用してボタンを作成し、それをボタンの背景画像として使用することもできます(その後、titleEdgeInsetsを使用してタイトルを移動します)。

84
Steven Canfield

レイモンドWの答えはここで最高です。カスタムlayoutSubviewsを持つUIButtonをサブクラス化します。非常に簡単に実行できますが、ここで私のために働いたlayoutSubviews実装があります:

- (void)layoutSubviews
{
    // Allow default layout, then adjust image and label positions
    [super layoutSubviews];

    UIImageView *imageView = [self imageView];
    UILabel *label = [self titleLabel];

    CGRect imageFrame = imageView.frame;
    CGRect labelFrame = label.frame;

    labelFrame.Origin.x = imageFrame.Origin.x;
    imageFrame.Origin.x = labelFrame.Origin.x + CGRectGetWidth(labelFrame);

    imageView.frame = imageFrame;
    label.frame = labelFrame;
}
54
Chris Miles

UIButtonのサブクラス化とlayoutSubviewsのオーバーライドはどうですか?

次に、self.imageViewおよびself.titleLabelの場所を後処理します

30
Raymond W

別の簡単な方法(iOS 9のみではない)は、UIButtonをサブクラス化してこれらの2つのメソッドをオーバーライドすることです

override func titleRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.titleRectForContentRect(contentRect)
    rect.Origin.x = 0
    return rect
}

override func imageRectForContentRect(contentRect: CGRect) -> CGRect {
    var rect = super.imageRectForContentRect(contentRect)
    rect.Origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(rect)
    return rect
}

contentEdgeInsetsは既にsuperを使用して考慮されています。

12
DrAL3X

Swiftの場合:

override func layoutSubviews(){
    super.layoutSubviews()

    let inset: CGFloat = 5

    if var imageFrame = self.imageView?.frame,
       var labelFrame = self.titleLabel?.frame {

       let cumulativeWidth = imageFrame.width + labelFrame.width + inset
       let excessiveWidth = self.bounds.width - cumulativeWidth
       labelFrame.Origin.x = excessiveWidth / 2
       imageFrame.Origin.x = labelFrame.Origin.x + labelFrame.width + inset

       self.imageView?.frame = imageFrame
       self.titleLabel?.frame = labelFrame  
    }
}
5
ChikabuZ

@splitによる答えの構築...

答えは素晴らしいですが、ボタンにカスタムイメージとタイトルエッジインセットが事前に設定されている(たとえば、ストーリーボードで)可能性があるという事実は無視されます。

たとえば、コンテナの上部と下部から画像にパディングを追加したいが、ボタンの右側に画像を移動したい場合があります。

私はこの方法で概念を拡張しました:-

- (void) moveImageToRightSide {
    [self sizeToFit];

    CGFloat titleWidth = self.titleLabel.frame.size.width;
    CGFloat imageWidth = self.imageView.frame.size.width;
    CGFloat gapWidth = self.frame.size.width - titleWidth - imageWidth;
    self.titleEdgeInsets = UIEdgeInsetsMake(self.titleEdgeInsets.top,
                                            -imageWidth + self.titleEdgeInsets.left,
                                            self.titleEdgeInsets.bottom,
                                            imageWidth - self.titleEdgeInsets.right);

    self.imageEdgeInsets = UIEdgeInsetsMake(self.imageEdgeInsets.top,
                                            titleWidth + self.imageEdgeInsets.left + gapWidth,
                                            self.imageEdgeInsets.bottom,
                                            -titleWidth + self.imageEdgeInsets.right - gapWidth);
}
4
BFar
// Get the size of the text and image
CGSize buttonLabelSize = [[self.button titleForState:UIControlStateNormal] sizeWithFont:self.button.titleLabel.font];
CGSize buttonImageSize = [[self.button imageForState:UIControlStateNormal] size];

// You can do this line in the xib too:
self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;

// Adjust Edge Insets according to the above measurement. The +2 adds a little space 
self.button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -(buttonLabelSize.width+2));
self.button.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, buttonImageSize.width+2);

これにより、次のように右揃えのボタンが作成されます。

[           button label (>)]

ボタンはコンテキストに応じて幅を調整しないため、ラベルの左側にスペースが表示されます。これを解決するには、buttonLabelSize.widthとbuttonImageSize.widthからボタンのフレーム幅を計算します。

2
caliss
button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
1
Todd Vanderlin

このソリューションはiOS 7以上で動作します

UIButtonをサブクラス化するだけ

@interface UIButton (Image)

- (void)swapTextWithImage;

@end

@implementation UIButton (Image)

- (void)swapTextWithImage {
   const CGFloat kDefaultPadding = 6.0f;
   CGSize buttonSize = [self.titleLabel.text sizeWithAttributes:@{
                                                               NSFontAttributeName:self.titleLabel.font
                                                               }];

   self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView.frame.size.width, 0, self.imageView.frame.size.width);
   self.imageEdgeInsets = UIEdgeInsetsMake(0, buttonSize.width + kDefaultPadding, 0, -buttonSize.width); 
}

@end

使用法(クラスのどこか):

[self.myButton setTitle:@"Any text" forState:UIControlStateNormal];
[self.myButton swapTextWithImage];
0
Pavel Volobuev

以前の回答に基づいて作成します。アイコンとボタンのタイトルの間にマージンを置きたい場合、コードを少し変更して、本質的なサイズのボタンの境界を超えてラベルとアイコンが浮かないようにする必要があります。

let margin = CGFloat(4.0)
button.titleEdgeInsets = UIEdgeInsetsMake(0, -button.imageView.frame.size.width, 0, button.imageView.frame.size.width);
button.imageEdgeInsets = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width, 0, -button.titleLabel.frame.size.width)
button.contentEdgeInsets = UIEdgeInsetsMake(0, margin, 0, margin)

最後のコード行は、自動レイアウトの本質的にコンテンツサイズの計算に重要です。

0
Kie