it-swarm.com.ru

iPhone UIButton - положение изображения

У меня есть UIButton с текстом «Исследовать приложение» и UIImage (>) В Interface Builder это выглядит так:

[ (>) Explore the app ]

Но мне нужно поместить это UIImage ПОСЛЕ текста:

[ Explore the app (>) ]

Как я могу переместить UIImage вправо?

108
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)
        }

    }

}

Где «отступ» будет пространство между заголовком и изображением.

5
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
110
Alvivi

Установите imageEdgeInset и titleEdgeInset для перемещения компонентов внутри вашего изображения. Вы также можете создать кнопку, используя полноразмерную графику, и использовать ее в качестве фонового изображения для кнопки (затем используйте titleEdgeInsets для перемещения заголовка).

83
Steven Canfield

Ответ Раймонда В. здесь лучший. Подкласс UIButton с пользовательским макетом Subviews. Чрезвычайно просто сделать, вот реализация 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 для переопределения этих двух методов.

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.

11
DrAL3X

В Свифте:

override func layoutSubviews()
{
    super.layoutSubviews()

    var imageFrame = self.imageView?.frame;
    var labelFrame = self.titleLabel?.frame;

    let inset: CGFloat = 5

    if var imageFrame = imageFrame
    {
        if var labelFrame = labelFrame
        {
            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
        }
    }
}
4
ChikabuZ

Построение ответа от @split ...

Ответ фантастический, но он игнорирует тот факт, что кнопка может иметь пользовательские вставки Edge изображения и заголовка, которые установлены заранее (например, в раскадровке). 

Например, вы можете захотеть, чтобы у изображения были отступы сверху и снизу контейнера, но все же переместите изображение в правую часть кнопки.

Я расширил концепцию с помощью этого метода: 

- (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