масштабировать изображение в UIButton до AspectFit?


97

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

Это то, что я пробовал, но это не работает:

  • Добавление изображения на кнопку и использование setContentMode:
[self.itemImageButton setImage:stretchImage forState:UIControlStateNormal];
[self.itemImageButton setContentMode:UIViewContentModeScaleAspectFit];
  • Делаем «растягивающее изображение»:
UIImage *stretchImage = [updatedItem.thumbnail stretchableImageWithLeftCapWidth:0 topCapHeight:0];

Я думаю, что это поведение было изменено по умолчанию в прошивке 4.0 и выше.
— Шаун Будрам

1
См. Решение на stackoverflow.com/a/28205566/481207 .
— Мэтт

Ответы:


28

Если вы действительно хотите масштабировать изображение, сделайте это, но вам следует изменить его размер перед использованием. Изменение его размера во время выполнения приведет к потере циклов процессора.

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

UIImage + Extra.h

@interface UIImage (Extras)
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
@end;

UIImage + Extra.m

@implementation UIImage (Extras)

- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

UIImage *sourceImage = self;
UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;

CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;

CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (!CGSizeEqualToSize(imageSize, targetSize)) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor) 
                scaleFactor = widthFactor;
        else
                scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image

        if (widthFactor < heightFactor) {
                thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        } else if (widthFactor > heightFactor) {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
}


// this is actually the interesting part:

UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width  = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if(newImage == nil) NSLog(@"could not scale image");


return newImage ;
}

@end

Вы можете использовать его до нужного размера. Подобно :

[self.itemImageButton setImage:[stretchImage imageByScalingProportionallyToSize:CGSizeMake(20,20)]];

Спасибо за ответ, Gcamp. У меня был метод изменения размера по соотношению. Но я все еще пытаюсь найти способ сказать UIButton сделать это за меня. Мое изображение загружено из Интернета, поэтому я не могу изменить его размер во время компиляции. Кстати, большое спасибо за ваш ответ.
— KONG

2
Поскольку изображение помещается в CALayer, визуализируется и кэшируется Quartz, производительность не должна ухудшаться, если вы поместите его туда в полном размере. В любом случае вы изменяете размер ~ 1 раз. Ответ gcamp гораздо важнее, если вы постоянно меняете размер кнопки или выполняете другие действия, которые заставят Quartz перерисовать слой изображения.
— Бен Готоу

похоже качество изображения ухудшилось. Тестирую на iphone 6 plus. Это правда? У меня тоже 3х изображение.
— Khant Thu Linn

Да, это довольно старый код. Это было UIGraphicsBeginImageContextвместо UIGraphicsBeginImageContextWithOptions. Просто исправил.
— gcamp

да, но во многих случаях это не имеет значения, если вы потеряете несколько циклов, так что нет смысла заправлять барана
— Раду Симионеску

204

У меня такая же проблема. Просто установите ContentMode для ImageView, который находится внутри UIButton.

[[self.itemImageButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[self.itemImageButton setImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal];

Надеюсь это поможет.


14
Убедитесь, что вы устанавливаете imageView . Я также немного не заметил, что я все еще использую backgroundImageView, и он не работал для этого.
— Alexandre Gomes

2
Кажется, у этого метода есть проблемы, когда состояние кнопки «подсвечено». Изображение вернется в режим заливки. Любая идея?
— Юаньфэй Чжу

У меня это не работает. Однако я заставляю его работать, используя [self.itemImageButton setbackgroundImage: [UIImage imageNamed: stretchImage] forState: UIControlStateNormal];
— Микки

3
Это сработало для меня. Я установил режим содержимого, как указано выше. Однако вам также необходимо установить такое же изображение выделенного состояния, чтобы изображение не возвращалось в «режим заливки». Например, [imageButton setImage: image forState: UIControlStateHighlighted];
— Кристофер

1
Вы можете сделать это в Интерфейсном imageView.contentModeNumber1
— Разработчике, указав

108

Ни один из ответов здесь не помог мне, я решил проблему с помощью следующего кода:

button.contentMode = UIViewContentModeScaleToFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Вы также можете сделать это в Интерфейсном Разработчике.

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


5
Это не дает вам подходящего поведения, как того требует OP.
— Ортвин Генц,

3
@OrtwinGentz ​​вы можете выбрать режим и установить Aspect fitвместо scale to fill.
— Даниэль

55

Самый простой способ программно установить UIButton imageView в режиме соотношения сторон :

Swift

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

Цель-C

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

Примечание: вы можете изменить .scaleAspectFit (UIViewContentModeScaleAspectFit) на .scaleAspectFill (UIViewContentModeScaleAspectFill), чтобы установить режим заполнения аспекта


20

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

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);

16

Теперь это можно сделать с помощью свойств UIButton IB. Ключ в том, чтобы установить ваше изображение в качестве фона, иначе это не сработает.

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


14

Расширяя ответ Дейва, вы можете установить все contentModeкнопки imageViewв IB, без какого-либо кода, используя атрибуты времени выполнения:

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

  • 1означает UIViewContentModeScaleAspectFit,
  • 2будет значить UIViewContentModeScaleAspectFill.

8

Если вы просто хотите уменьшить изображение кнопки:

yourButton.contentMode = UIViewContentModeScaleAspectFit;
yourButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

Это должно быть yourButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
— sdsykes

Не пробовал с .imageView. Работает без него неплохо.
— Tulleb 08

6

1 - очистить текст кнопки по умолчанию (важно)

2 - установить выравнивание как изображение

3 - установить режим содержимого как изображение

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


Хороший ответ, брат ... мне очень помог. Благодарность!
— BharathRao

5

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

-(void)makeImageAspectFitForButton:(UIButton*)button{
    button.imageView.contentMode=UIViewContentModeScaleAspectFit;
    button.contentHorizontalAlignment=UIControlContentHorizontalAlignmentFill;
    button.contentVerticalAlignment=UIControlContentVerticalAlignmentFill;
}

4

Лучшее решение - использовать Auto Layout . Опустив Content Приоритет сжатия сопротивления из моих UIButtonи установить изображение (не Фоновое изображение ) с помощью Interface Builder . После этого я добавил пару ограничений, которые определяют размер моей кнопки (довольно сложно в моем случае), и это сработало как шарм.


У меня это сработало, но только если я выбрал «Фоновое изображение», а не фактическое изображение. Все, что работает! Это сводило меня с ума.
— Энди,

Под Xcode 6.2 это сработало для меня, но, как сказал @AndrewHeinlein, использовалBackground Image
— RoLYroLLs

3

убедитесь, что вы установили для изображения свойство Image, но не значение Background


2

Фоновое изображение можно довольно легко настроить для масштабирования заливки сторон. Просто нужно сделать что-то вроде этого в подклассе UIButton:

- (CGRect)backgroundRectForBounds:(CGRect)bounds
{
    // you'll need the original size of the image, you 
    // can save it from setBackgroundImage:forControlState
    return CGRectFitToFillRect(__original_image_frame_size__, bounds);
}

// Utility function, can be saved elsewhere
CGRect CGRectFitToFillRect( CGRect inRect, CGRect maxRect )
{
    CGFloat origRes = inRect.size.width / inRect.size.height;
    CGFloat newRes = maxRect.size.width / maxRect.size.height;

    CGRect retRect = maxRect;

    if (newRes < origRes)
    {
        retRect.size.width = inRect.size.width * maxRect.size.height / inRect.size.height;
        retRect.origin.x = roundf((maxRect.size.width - retRect.size.width) / 2);
    }
    else
    {
        retRect.size.height = inRect.size.height * maxRect.size.width / inRect.size.width;
        retRect.origin.y = roundf((maxRect.size.height - retRect.size.height) / 2);
    }

    return retRect;
}

Разве это невозможно без подкласса?
— Юлиан

Этот ответ был специально для backgroundImage. Для основного изображения вы можете обезьянничать с файлом imageEdgeInsets.
— Энди

Я знаю и хотел, чтобы этого можно было добиться без подкласса.
— Юлиан

Насколько мне известно, вы не можете настроить backgroundImage без создания подклассов.
— Энди


0

Для Xamarin.iOS (C #):

    myButton.VerticalAlignment = UIControlContentVerticalAlignment.Fill;
    myButton.HorizontalAlignment = UIControlContentHorizontalAlignment.Fill;
    myButton.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;

-1

Вам просто нужно установить режим содержимого UIButton imageview для трех событий. -

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateNormal];

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateHighlighted];

[cell.imgIcon setImage:[UIImage imageWithData:data] forState:UIControlStateSelected];

У нас есть код для трех событий bcoz при выделении или выборе, если размер кнопки - КВАДРАТ, а размер изображения - прямоугольник, тогда оно будет показывать квадратное изображение во время выделения или выбора.

Я уверен, что это сработает для вас.


Вы не устанавливаете режим содержимого, вы устанавливаете изображение. И это не события, это состояния. Вы устраиваете большой беспорядок. Это совершенно не связано с вопросом.
— manecosta 07
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.