UIButton не переходит в Aspect Fit на iPhone

105

У меня есть пара UIButton, и в IB они настроены на Aspect Fit, но по какой-то причине они всегда растягиваются. Вам нужно что-то еще установить? Я перепробовал все разные режимы просмотра, и ни один из них не работает, все растягиваются.

Марти
источник
Ответ @Werner Altesischer правильный. Внесите соответствующие изменения.
Harshit Gupta
1
@marty Вы устанавливаете фоновое изображение или изображение? фоновое изображение не поддерживает его, только изображение.
Хуан Боэро

Ответы:

45

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

РЕДАКТИРОВАТЬ: этот ответ устарел. См. Ответ @Werner Altewischer для правильного ответа в современных версиях iOS.

Дэн Рэй
источник
Да, пробовал, но теперь не могу получить кнопку, чтобы восстановить изображение
Марти
Как с помощью этой техники управлять состояниями кнопок? Похоже, что реагирование на взаимодействие с пользователем типа «выделено» было бы кошмаром.
SooDesuNe
3
Возможно, это был правильный способ сделать это 2,5 года назад, когда на этот вопрос был дан ответ, но теперь вы можете отредактировать внутренний ImageView UIButton и установить там режим содержимого. См. Ответ @Werner Altewischer
Стив Хейли
233

Решение состоит в том, чтобы установить свойство contentModeв imageViewсвойстве UIButton. UIButtonДолжен быть создан с помощью пользовательского типа для этой работы я считаю , ( в противном случае nilвозвращается для этого свойства).

Вернер Альтевишер
источник
67
У меня это сработало:[button.imageView setContentMode:UIViewContentModeScaleAspectFit];
ayreguitar 08
2
Это работает и для меня, но если я установил adjustsImageWhenHighlighted = YES, изображение снова растягивается, когда я нажимаю на кнопку.
cduck 01
1
Растягивание в adjustsImage было устранено в iOS 6.
Бен Флинн,
3
В iOS 8 это на самом деле не работает. Исходный ответ (с размещением imageView за прозрачной кнопкой) работает лучше всего.
user1416564
3
в Swift du jour:button.imageView!.contentMode = UIViewContentMode.scaleAspectFit
Нестор
57

Этот метод мне очень понравился:

В Xib выберите кнопку и установите user defined runtime attributes:

  • Ключевой путь: self.imageView.contentMode
  • Тип: Number
  • Стоимость: 1

Щелкните здесь, чтобы более подробно ознакомиться с решением

Мы используем число, потому что вы не можете использовать там enum. Но UIViewContentModeScaleAspectFit равен 1.

Иштван Стефанович
источник
2
Это также обновило изображение в построителе интерфейса во время разработки. Отличное решение.
Джордж Филиппакос
Отличное решение, немного кода и работает как шарм, перечисление основано на элементах списка режима содержимого.
Kross
Вы также можете добавить расширение, чтобы упростить задачу: extension UIButton { @IBInspectable var imageContentMode: Int { get {return imageView?.contentMode.rawValue ?? 0} set {imageView?.contentMode = UIViewContentMode(rawValue: newValue) ?? .scaleAspectFit} } }
Йонат,
Без «себя» imageView.contentModeу меня работало!
byJeevan
22

Если вы делаете это в Interface Builder, вы можете использовать инспектор атрибутов среды выполнения, чтобы установить это напрямую без какого-либо кода.

Задайте для ключевого пути на кнопке значение «imageView.contentMode» с типом «Число» и значением «1» (или любым другим режимом, который вам нужен).

imageview.contentMode = 1

Аверидев
источник
14

Используйте кнопку imageView для contentMode. Не прямо на самой кнопке.

homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];
Ахмед Элашкер
источник
6

Если вы поместите изображение UIImageViewпозади кнопки, вы потеряете встроенную функциональность UIButtonкласса, такую ​​как adjustsImageWhenHighlightedи adjustsImageWhenDisabled, и, конечно же, возможность устанавливать разные изображения для разных состояний (без необходимости делать это самостоятельно).

Если мы хотим, чтобы изображение не было растянутым для всех состояний управления , одна из возможностей - получить изображение с помощью imageWithCGImage:scale:orientation, как в следующем методе:

- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {

    // Check which dimension (width or height) to pay respect to and
    // calculate the scale factor
    CGFloat imgRatio = img.size.width / img.size.height, 
            btnRatio = btn.frame.size.width / btn.frame.size.height,
            scaleFactor = (imgRatio > btnRatio 
                           ? img.size.width / btn.frame.size.width
                           : img.size.height / btn.frame.size.height;

    // Create image using scale factor
    UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
                                             scale:scaleFactor
                                       orientation:UIImageOrientationUp];
    return scaledImg;
}

Чтобы реализовать это, мы должны написать:

UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];

Это должно предотвратить растяжение изображения во всех состояниях управления. Это сработало для меня, но дайте мне знать, если это не так!

ПРИМЕЧАНИЕ. Здесь мы обращаемся к проблеме, относящейся к тому UIButton, что insideButton:может быть insideView:, или к чему бы вы ни хотели вписать изображение.

Александр Валлин
источник
6

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

Хитрость заключается в том, чтобы установить его как просто изображение, а затем применить технику @ayreguitar, и это должно исправить!

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];
Джо Барбур
источник
4

Это сработало для меня

[button.imageView setContentMode:UIViewContentModeScaleAspectFit];

Спасибо @ayreguitar за его комментарий

Каран Алангат
источник
4

Вот быстрый альтернативный ответ:

myButton.imageView?.contentMode = .ScaleAspectFit
Жуан Невес
источник
4

Объединение нескольких разных ответов в одно решение - создайте кнопку с настраиваемым типом, установите для кнопки свойство imageView contentMode и установите изображение для кнопки (не фоновое изображение, которое по-прежнему будет масштабироваться для заполнения).

//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)
Мошенник
источник
3
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;
Selaband
источник
Хотя этот фрагмент кода может решить вопрос, включение объяснения действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причины вашего предложения кода. - Из обзора
Ferrybig
2

Этот ответ основан на ответе @ WernerAltewischer .

Чтобы не подключать мою кнопку к IBOutlet для выполнения кода на нем, я создал подклассы класса UIButton:

// .h
@interface UIButtonWithImageAspectFit : UIButton
@end

// .m
@implementation UIButtonWithImageAspectFit

- (void) awakeFromNib {
    [self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}

@end



Теперь создайте пользовательскую кнопку в своем xib и установите ее изображение (а не фоновое изображение):

UIButtonWithImageAspectFit: создать и установить изображение


Затем установите его класс:

UIButtonWithImageAspectFit: установить собственный класс

Готово!
Вместо
UIButton без соотношения сторон изображения
вашего баттона аспекта изображения приступе теперь , как и ожидалось:
UIButton с размером изображения

Гийом
источник
2

ios 12. Также необходимо добавить контент Alignment

class FitButton: UIButton {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)


    }

    override func layoutSubviews() {
        self.imageView?.contentMode = .scaleAspectFill
        self.contentHorizontalAlignment = .fill
        self.contentVerticalAlignment = .fill
        super.layoutSubviews()


    }

}
Жуан Нуньес
источник
1

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

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);
ниндзянин
источник
1

Режимы содержимого UIView применяются к соответствующему «содержимому» CALayer. Это работает для UIImageViews, потому что они устанавливают соответствующий CALayerконтент CGImage.

drawRect: в конечном итоге отображает содержимое слоя.

Пользовательский UIButton(насколько мне известно) не имеет содержимого (кнопки в стиле прямоугольника с закругленными углами могут отображаться с использованием содержимого). У кнопки есть подвиды: фон UIImageView, изображение UIImageViewи заголовок UILabel. Установка для contentModeвложенных представлений может делать то, что вы хотите, но возиться с UIButtonиерархией представлений - это немного недопустимо.

tc.
источник
1

Смена UIButton.imageView.contentModeне сработала.
Я решил проблему, установив для изображения свойство «Фон».
Вы можете добавить ограничение соотношения, если вам нужно

Soohwan Park
источник
1

Это перекрывает многие другие ответы, но решение для меня заключалось в том, чтобы

  • установить contentModeиз UIImageViewза кнопки на .ScaleAspectFit- которые либо может быть сделано в «User Defined выполнения Атрибуты» в Interface Builder (то есть. self.imageView.contentMode, номер, 1) или вUIButton подклассе;
  • отключите «Автоизменение размеров вложенных изображений»;
  • установите «Край» на «Изображение» и соответствующие значения «Сверху» и «Снизу» для «Вставки» (что может потребоваться только в том случае, если вы, как и я, использовали PDF-файл в качестве изображения).
Plindberg
источник
0

Вы можете использовать imageWithCGImage, как показано выше (но без отсутствующих скобок).

Кроме того ... миллионы телефонов, не поддерживающих 4.0, вообще не будут работать с этим кодом.

Алиса
источник
0

Как и @Guillaume, я создал подкласс UIButton как Swift-файл. Затем установите мой собственный класс в Интерфейсном Разработчике:

построитель интерфейса.

И вот файл Swift:

import UIKit

class TRAspectButton : UIButton {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.imageView?.contentMode = .ScaleAspectFit
    }
}
Motine
источник
-1

У меня была такая же проблема, но я не мог заставить ее работать (возможно, это ошибка SDK).

В конце концов, как обходной путь, я поместил UIImageViewза своей кнопкой и установил UIButtonдля нее нужные параметры, а затем просто поместил поверх нее пробел .

Аншу Чимала
источник
7
Здесь есть эхо? ;-)
Дэн Рэй