「アプリを探す」というテキストとUIButton
(>)を含むUIImage
がありますInterface Builder
では、次のようになります。
[ (>) Explore the app ]
しかし、テキストの後にこのUIImage
を配置する必要があります。
[ Explore the app (>) ]
UIImage
を右に移動するにはどうすればよいですか?
アプリが「左から右」と「右から左」の両方をサポートしている場合、ボタンに「右から左」を強制することはオプションではありません。
私のために働いたソリューションは、ストーリーボードのボタンに追加できるサブクラスであり、制約でうまく機能します(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)
}
}
}
「パディング」とは、タイトルと画像の間のスペースです。
これに対する私の解決策は非常に簡単です
[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);
imageEdgeInset
とtitleEdgeInset
を設定して、画像内でコンポーネントを移動します。フルサイズのグラフィックスを使用してボタンを作成し、それをボタンの背景画像として使用することもできます(その後、titleEdgeInsets
を使用してタイトルを移動します)。
レイモンド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;
}
UIButton
のサブクラス化とlayoutSubviews
のオーバーライドはどうですか?
次に、self.imageView
およびself.titleLabel
の場所を後処理します
別の簡単な方法(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を使用して考慮されています。
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
}
}
@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);
}
// 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からボタンのフレーム幅を計算します。
button.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
このソリューションは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];
以前の回答に基づいて作成します。アイコンとボタンのタイトルの間にマージンを置きたい場合、コードを少し変更して、本質的なサイズのボタンの境界を超えてラベルとアイコンが浮かないようにする必要があります。
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)
最後のコード行は、自動レイアウトの本質的にコンテンツサイズの計算に重要です。