Запрос на выравнивание заголовка и изображения UIButton

У меня есть UIButton, и я пытаюсь установить для него заголовок и изображение.

Я хочу выровнять заголовок для UIButton по левому краю и разместить изображение по правому краю. Я пытаюсь получить внешний вид кнопки в приложении «Таймер в часах» (та, которая говорит «Когда таймер заканчивается»).

Я возился с contentHorizontalAlignment, contentEdgeInsets, titleEdgeInsets и imageEdgeInsets, чтобы достичь своей цели, но безрезультатно. Документация также довольно скудна.

Как я могу добиться того же?

Также связанные вопросы, приложение «Таймер в часах» имеет два набора текста, один выровнен по левому краю, а другой по правому краю изображения? Как это можно сделать в UIButton? (Хотя на данный момент мне эта функция не нужна).


person siasl    schedule 12.07.2009    source источник


Ответы (9)


Измените свойство imageEdgeInsets на UIButton, а затем просто используйте setImage:forState:

person Bill    schedule 25.10.2010
comment
Это правильный способ сделать это, если вы используете UIButton. виды за столом - другой зверь. - person Aleksandar Vacić; 18.11.2010
comment
Согласен, но OP не упомянул представления таблиц :) - person Bill; 19.11.2010

Вот код, который я использую для этого:

//Right-align the button image
CGSize size = [[myButton titleForState:UIControlStateNormal] sizeWithFont:myButton.titleLabel.font];
[myButton setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -size.width)];
[myButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 0, 0, myButton.imageView.image.size.width + 5)];
person ingham    schedule 07.11.2011
comment
Это IMO несколько лучший, хотя и несколько излишне краткий, ответ с использованием кода по сравнению с ответом, получившим наибольшее количество голосов от @Bill, который говорит вам использовать эти вызовы API, но не показывает их вызов. Было бы лучше, если бы он показывал вызов setImage: forState :. Кроме того, я обнаружил, что в некоторых случаях, таких как actionSheets, после того, как вы установилиImageEdgeInsets, вам не нужно настраивать titleEdgeInsets - они уже приняли во внимание ширину вашего изображения. YMMV. - person natbro; 15.01.2012
comment
Если вы установите contentHorizontalAlignment на UIControlContentHorizontalAlignmentRight, вам также необходимо добавить вставку слева в titleEdgeInsets. Это: [myButton setTitleEdgeInsets:UIEdgeInsetsMake(0, -imageSize.width, 0, imageSize.width)]; - person vilanovi; 13.02.2013

Следующий код работает:

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = buttonRect;
[button setTitle:@"A title" forState:UIControlStateNormal];
[button setImage:buttonImage forState:UIControlStateNormal];
button.imageEdgeInsets = UIEdgeInsetsMake(0.0, WIDTH(button.titleLabel) + 10.0, 0.0, 0.0);
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
person yaris    schedule 10.07.2012

Помните, что UIButton наследуется от UIView, поэтому вы можете добавлять в него подвиды, как и в любое другое представление. В вашей ситуации вы должны создать кнопку, а затем добавить UILabel слева и UIImage справа:

// Create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

// Now load the image and create the image view
UIImage *image = [UIImage imageNamed:@"yourImage.png"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(/*frame*/)];
[imageView setImage:image];

// Create the label and set its text
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(/*frame*/)];
[label setText:@"Your title"];

// Put it all together
[button addSubview:label];
[button addSubview:imageView];
person Tim    schedule 12.07.2009
comment
Кажется, это не слишком хорошо работает. У меня есть фоновое изображение на кнопке, и метка не отображается, если я установил фоновое изображение. Если я уберу фоновое изображение с кнопки, метка станет видимой? Я добавил ярлык в родительский вид UIButton и выровнял его так, чтобы он располагался поверх UIButton, и тогда он работал. Есть идеи, почему он так себя ведет? - person siasl; 12.07.2009
comment
Обычно такое поведение проявляется, когда фоновое изображение добавляется как часть UIButton поверх ваших пользовательских представлений. Вместо того, чтобы устанавливать свойство backgroundImage кнопки, подумайте о добавлении UIImageView самостоятельно для фонового изображения, а затем добавьте другое настраиваемое содержимое поверх этого представления изображения. - person Tim; 12.07.2009
comment
Не нужно наворачивать собственную логику - используйте свойство imageEdgeInsets в UIButton и setImage:forState:. - person Bill; 27.01.2011
comment
ОП специально сказал: Я возился с ... imageEdgeInsets, чтобы достичь своей цели, но безрезультатно. - person Tim; 27.01.2011
comment
В этом ответе предлагается создать новую кнопку UIImageView внутри, у которой она уже есть. Это определенно работает, но рекомендуемое решение будет включать imageRectForContentRect: и titleRectForContentRect:, которые специально предназначены для этой цели. - person cleverbit; 18.11.2013
comment
@ Тим, спасибо за код, скажите, пожалуйста, как я могу программно изменить изображение imageView при нажатии кнопки ?? - person Varun Naharia; 01.06.2015
comment
@VarunNaharia: Лучшее, что можно посоветовать по этому поводу, - это задать новый вопрос, а не использовать комментарии к этому (которому почти шесть лет!). - person Tim; 01.06.2015
comment
@Tim см. Здесь stackoverflow.com/questions/30577908/ - person Varun Naharia; 01.06.2015
comment
@ Тим У тебя есть ответ на этот вопрос или нет? - person Varun Naharia; 02.06.2015
comment
Похоже, вы уже приняли ответ на этот вопрос. Пожалуйста, прекратите повторно использовать комментарии к этому старому вопросу для обсуждения других тем! - person Tim; 02.06.2015

Вы также можете переопределить методы titleRectForContentRect: и imageRectForContentRect: UIButton, чтобы разместить текст и изображение в любом месте.

person ohnit    schedule 09.08.2013

В Swift для всех, кого это волнует (с интервалом 10pt):

let size = (self.titleForState(UIControlState.Normal)! as NSString).sizeWithAttributes([NSFontAttributeName:self.titleLabel!.font])
let offset = (size.width + 10)
self.imageEdgeInsets = UIEdgeInsetsMake(0, offset, 0, -offset)
self.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, self.imageView!.frame.size.width + 10)
person Brenden    schedule 12.01.2016

Для использования на iOS 9 я пробовал много ответов в этой теме, но ни один из них мне не подошел. Я нашел для себя следующий ответ:

class MyButton: UIButton {

  override func layoutSubviews() {
    super.layoutSubviews()

    self.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left

    if self.imageView?.image != nil {
      // Move icon to right side
      self.imageEdgeInsets = UIEdgeInsets(
        top: 0,
        left: self.bounds.size.width - self.imageView!.image!.size.width,
        bottom: 0,
        right: 0)

      // Move title to left side
      self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView!.frame.size.width + 8, 0, 0)

    }
  }
}

SWIFT 3:

class MyButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        self.contentHorizontalAlignment = UIControlContentHorizontalAlignment.left

        if self.imageView?.image != nil {
            // Move icon to right side
            self.imageEdgeInsets = UIEdgeInsets(
                top: 0,
                left: self.bounds.size.width - self.imageView!.image!.size.width,
                bottom: 0,
                right: 0)

            // Move title to left side
            self.titleEdgeInsets = UIEdgeInsetsMake(0, -self.imageView!.frame.size.width + 8, 0, 0)

        }
    }
}

Надеюсь, это поможет кому-нибудь в этом деле, как мне!

person Quang Tran    schedule 30.09.2016
comment
Отличная работа, я рассказываю вам о Swift 3 - person Mikel Sanchez; 20.10.2016

Вот подкласс UIButton в Swift, который выравнивает изображение слева и текст в центре. Установите imageLeftInset на желаемое значение.

class LeftImageAlignedButton : UIButton {

var imageLeftInset : CGFloat = 10.0

override func layoutSubviews() {
    super.layoutSubviews()
    self.contentHorizontalAlignment = .Left
    if let font = titleLabel?.font {
        let textWidth = ((titleForState(state) ?? "") as NSString).sizeWithAttributes([NSFontAttributeName:font]).width
        let imageWidth = imageForState(state)?.size.width ?? 0.0
        imageEdgeInsets = UIEdgeInsets(top: 0, left: imageLeftInset, bottom: 0, right: 0)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: bounds.width/2 - textWidth/2.0 - imageWidth, bottom: 0, right: 0)
    }
}
}
person Mike Pollard    schedule 13.05.2015

Создайте подкласс UIButton и переопределите его метод layoutSubviews, чтобы программно выровнять текст и изображение. Или используйте что-то вроде https://github.com/stevestreza/BlockKit/blob/master/Source/UIView-BKAdditions.h, чтобы можно было реализовать layoutSubviews с помощью блока.

person Steven Kramer    schedule 01.03.2012
comment
Нет проблем, хотя я не уверен, что стоит использовать этот механизм вместо простого подкласса. - person Steven Kramer; 03.09.2013
comment
Хотя это хорошая стратегия для просмотров в целом, -(CGRect) imageRectForContentRect:(CGRect)contentRect и -(CGRect) titleRectForContentRect:(CGRect)contentRect предназначены специально для этой цели. К сожалению, layoutSubviews будет вызываться каждый раз при изменении макета представления, что делает его непригодным в данном случае. - person cleverbit; 18.11.2013
comment
Но я готов поспорить imageRectForContentRect: и др. также вызываются на макете - и мне интересно, почему вы думаете, что этот случай делает его непригодным? Кроме того, layoutSubviews дает вам полный контроль над макетом за один раз, что тоже приятно. Я предполагаю, что это зависит от того, что IIRC правильно. У меня были проблемы с созданием кнопки с выровненным по верхнему краю значком и нижним выравниванием текста (с использованием… forContentRect). - person Steven Kramer; 19.11.2013