UIButton не слушает настройку режима содержимого?

92

firstButton - это UIButton типа Custom. Я программно помещаю три из них в каждую ячейку таблицы, таким образом:

[firstButton setImage:markImage forState:UIControlStateNormal];
[firstButton setContentMode:UIViewContentModeScaleAspectFit];
[cell.contentView addSubview:firstButton];

В другом месте я говорю это clipToBounds. Я получаю обрезку центрального квадрата изображения, а не его рендеринг с масштабированием по сторонам. Я пробовал это множество способов, включая установку свойства режима в firstButton.imageView, что тоже, похоже, не работает.

Дэн Рэй
источник
1
См. Решение Криса Ноле ниже: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Мэтт
См. Stackoverflow.com/a/28205566/481207, где показано, что для UIViewContentModeScaleAspectFit требуется установка contentVerticalAlignment и contentHorizontalAlignment.
Мэтт

Ответы:

187

У меня такая же проблема. Я вижу, что этот вопрос немного устарел, но я хочу дать четкий и правильный ответ, чтобы сэкономить время другим людям (например, мне), когда он появится в их результатах поиска.

Мне потребовалось немного поисков и экспериментов, но я нашел решение. Просто установите ContentMode «скрытого» ImageView, который находится внутри UIButton.

[[firstButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[firstButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];

Возможно, именно это имел в виду Дэн Рэй в своем принятом ответе, но я подозреваю, что нет.

Дэйв
источник
1
Нет, не было. Решение, на котором я остановился, заключалось в использовании UIImageView для хранения изображения, а затем поверх него четкого прозрачного UIButton типа custom.
Дэн Рэй
Дейв, по крайней мере, на iOS 3.2 ваше решение не работает для меня. Жаль, потому что я надеялся получить выделение изображения по клику «бесплатно». Я даже убедился, что button.imageView не был равен нулю там, где я устанавливал contentMode, и установил изображение после установки contentMode, как и вы.
Жак
2
Чтобы уточнить, «не работает» означает «изображение отображается в полном разрешении, а не в уменьшенном масштабе, как я надеялся».
Жак
Жак, все вышесказанное у меня работает в iOS 4.x. К сожалению, я могу воспроизвести проблему «не изменять размер» при сборке с целью v3.2. Я попытался изменить размер кадра представления UIButton, но это тоже не помогло. тьфу.
Дэйв
4
См. Решение Криса Ноле ниже: button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;
Мэтт
74

Если вы имеете дело с изображением UIButton (в отличие от backgroundImage), установка contentMode в самом UIButton или в его imageView не имеет никакого эффекта (несмотря на то, что говорят другие ответы).

В качестве альтернативы сделайте это:

self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Или измените размер изображения соответствующим образом.

ИЛИ просто используйте UIImageView (который должным образом уважает contentMode) с прикрепленным к нему UITapGestureRecognizer или прозрачным UIButton поверх него.

Альфи Ханссен
источник
4
В моем случае это работает в iOS 7, тогда как все остальные здесь - нет.
Байт
5
Установка contentHorizontalAlignment и contentVerticalAlignment - правильное решение. См. Stackoverflow.com/a/28205566/481207 для объяснения.
Мэтт
1
Это ответ, который я искал.
ninjaneer
4
Это неверный ответ. Вы действительно должны установить contentModeна , imageViewесли вы хотите сделать любой вид заливки сторон или приступа, как и другие ответы выяснены. Обратитесь: stackoverflow.com/a/7944316/746890 .
Крис Нолет 02
52

Вместо того, чтобы устанавливать contentModeна самой кнопке, вы захотите установить contentHorizontalAlignmentи contentVerticalAlignmentсвойства и (что особенно важно) contentModeдля кнопки imageViewдля любого вида заливки или подгонки. Вот пример:

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

Конечно, вы также можете делать другие вещи, например выравнивать изображение кнопки по верхнему краю кнопки. Если вам не требуется заливка или подгонка аспекта, вы можете просто установить выравнивание самостоятельно:

button.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

В Swift вы захотите использовать:

button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit

Это работает для всех версий iOS, включая последние версии с автоматической компоновкой (например, от iOS 4 до iOS 11+).

Крис Нолет
источник
2
Спасибо, Крис, это решило мою проблему, или, скорее, это было сделано в сочетании с contentEdgeInsets, чтобы немного отодвинуть мое изображение от верхнего края.
Роб Ройсс,
7

После пары часов путаницы вот как я заставил его работать под iOS 3.2. Как упоминал Дускер, использование setBackgroundImage вместо setImage сделало мою работу за меня.

CGRect myButtonFrame = CGRectMake(0, 0, 250, 250);
UIImage *myButtonImage = [UIImage imageNamed:@"buttonImage"];

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];

[myButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
[myButton setFrame: myButtonFrame];
[myButton setContentMode: UIViewContentModeScaleAspectFit];
Пьер
источник
6

Ответ - использовать UIImageView со всеми желаемыми прекрасными настройками Content Mode, а затем наложить поверх него настраиваемую кнопку. Тупой, что вы не можете сделать это за один раз, но похоже, что вы не можете.

Дэн Рэй
источник
4

Нашел исправление для этого. Установите adjustsImageWhenHighlightedсвойство в UIButtonзначение NO.

  UIButton *b = [[UIButton alloc] initWithFrame:rect];
        [b setImage:image forState:UIControlStateNormal];
        [b.imageView setContentMode:UIViewContentModeScaleAspectFill];
        [b setAdjustsImageWhenHighlighted:NO];

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

iOSDevSF
источник
Это идеальное решение.
Gaurav
Не работает. Это просто предотвращает выделение кнопки.
Мэтт
4

Мой ответ похож на ответ Кубы. Мне нужно, чтобы мое изображение было установлено программно.

UIImage *image = [[UIImage alloc] initWithContentsOfFile:...];
[button setBackgroundImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill; //this is needed for some reason, won't work without it.
for(UIView *view in button.subviews) {
    view.contentMode = UIViewContentModeScaleAspectFill;
}
ниндзянин
источник
3

Единственное решение, которое сработало для меня:

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
Тарик
источник
3

Swift 3

self.firstButton.imageView?.contentMode = .scaleAspectFill
Вайбхав Саран
источник
1

Вместо setImage попробуйте setBackgroundImage

сумеречный
источник
3
Хмп. О, это глупо, он должен соблюдать настройку CONTENT MODE для своего CONTENT, верно? И B, он ВСЕГДА, похоже, не соблюдает настройку режима - теперь он заблокирован на «растяжение» (что в данном случае больше похоже на «сжатие») и не масштабирует контент в соответствии с его аспектом. соотношение.
Дэн Рэй
1

Я считаю, что здесь есть простая проблема с построителем интерфейса - очевидно, IB игнорирует любые изменения режима содержимого ПОСЛЕ того, как вы установили свойство image.

решение очень простое: установите режим содержимого, удалите ранее установленные имена изображений (убедитесь, что вы удалили его во всех состояниях, по умолчанию, выделены и т. д.), затем повторно введите желаемые имена изображений во всех желаемых состояниях - et voilà .

JohnPayne
источник
1
то же самое касается программной установки режима содержимого - не устанавливайте изображение ДО установки режима содержимого
JohnPayne
0

Я также советую взглянуть на adjustsImageWhenHighlighted UIButtonсвойство, чтобы избежать странных деформаций изображения при нажатии кнопки.

MonsieurDart
источник
0

Пытаясь понять это, мой метод со временем стал немного хакерским, и я создал подкласс UIButton и переопределил setHighlighted:

Для меня это работает, чтобы просто сбить изображение с альфа до 0,5, потому что они находятся на черном фоне.

Однако это сработает только в том случае, если я закомментирую [super setHighlighted:] (там, где, по-видимому, происходит растягивающий код изображения), что просто не похоже на правильный способ решить эту проблему ... все кажется хотя работает нормально. Мы увидим, как это работает, когда я продолжу над этим работать.

- (void)setHighlighted:(BOOL)highlight {
    if (highlight) {
        [self.imageView setAlpha:.5];
    }  else {
        [self.imageView setAlpha:1];        
    }

//    [super setHighlighted:highlight];
}
Jankins
источник
1
На случай, если кто-то сочтет это подходящим, мой вышеупомянутый метод, казалось, работал нормально, пока я не помещал кнопки в UIScrollView, где иногда подсветка кнопки «застревала», что, как я подозревал, могло в конечном итоге произойти.
jankins 03
0

Если кто-то ищет ответ, который работает в iOS 6 и iOS 7 и раскадровке:

Вы можете установить изображение в раскадровке:

введите описание изображения здесь

А потом:

for(UIView* testId in self.subviews) {
    if([testId isKindOfClass:[UIImageView class]])
        [testId setContentMode:UIViewContentModeScaleAspectFill];
}
Якуб
источник
0

Если кажется, что UIButton не слушает настройки ограничения макета, проверьте, не превышают ли изображения размер кнопки. Всегда используйте изображения @ 2x и @ 3x для разрешений сетчатки.

Тоторо
источник
0

Эти две вещи (которые довольно сложно найти изначально) растянут ваше изображение UIButton до размера кнопки:

введите описание изображения здесь введите описание изображения здесь

всегда следует пытаться установить это в раскадровке, а не в коде.

delta2flat
источник