зображення масштабу в UIButton для AspectFit?


94

Я хочу додати зображення до 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 зробити це для мене. Моє зображення завантажується з Інтернету, тому я не можу змінити його розмір під час компіляції. До речі, дуже дякую за вашу відповідь.
КОНГ

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

схоже, якість зображення знижується. я тестую на iphone 6 plus. Це правда? У мене також є 3x зображення.
Хант Ту Лінн

Так, так, цей код досить старий. Це було UIGraphicsBeginImageContextзамість UIGraphicsBeginImageContextWithOptions. Просто виправили це.
gcamp

так, але в багатьох випадках не має значення, якщо ви втратите кілька циклів, тому немає сенсу заповнювати барана
Раду Сіміонеску

203

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

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

Сподіваюся, це допомагає.


14
Переконайтеся, що ви встановлюєте imageView . Я також трохи не помітив, що я все ще використовую backgroundImageView, і це не працює для цього.
Олександр Гомес

2
Здається, у цього методу є деякі проблеми, коли стан кнопки "виділено". Зображення повернеться в режим заливки. Будь-яка ідея?
Yuanfei Zhu

Мені це не працює. Однак я змушую його працювати, використовуючи [self.itemImageButton setbackgroundImage: [UIImage imageNamed: stretchImage] forState: UIControlStateNormal];
Міккі

3
Це працювало для мене. Я встановлюю режим вмісту як вище. Однак вам також потрібно встановити однакове зображення виділеного стану, щоб уникнути повернення зображення до «режиму заповнення». Наприклад, [imageButton setImage: image forState: UIControlStateHighlight];
Крістофер

1
Зробити це можна в програмі Interface Builder за допомогою ключового шляху imageView.contentMode, типу Numberта значення1
bendytree

107

Жодна з відповідей тут насправді не працювала для мене, я вирішив проблему за допомогою наступного коду:

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

Ви також можете це зробити у програмі Interface Builder.

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


5
Це не надає вам аспектної поведінки відповідно до запитання ОП.
Ортвін Генц

3
@OrtwinGentz ​​ви можете вибрати режим і встановити Aspect fitзамість нього scale to fill.
Даніель

55

Найпростіший спосіб програмно задати UIButton ImageView в пригону аспекту режимі:

Швидкий

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

Ціль-С

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. Це працює не дуже добре.
Туллеб

5

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

2 - встановити вирівнювання як зображення

3 - встановити режим вмісту, як зображення

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


Гарна відповідь, брато ... мені дуже допомогло. Дякую!
BharathRao

5

У мене є метод, який робить це для мене. Метод сприймає UIButtonі робить аспект зображення відповідним.

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

4

Найчистішим рішенням є використання автоматичного макета . Я знизив свій пріоритет на опір стисненню вмістуUIButton і встановив зображення (не фонове зображення ) за допомогою Interface Builder . Після цього я додав пару обмежень, які визначають розмір моєї кнопки (в моєму випадку досить складний), і це спрацювало як шарм.


Це працювало для мене - але лише в тому випадку, якщо я вибрав використовувати "Фонове зображення", а не власне зображення. Що б не працювало! Це водило мене НАГАДКИ.
Енді

Під Xcode 6.2 це працювало для мене, але, як сказав @AndrewHeinlein, використаноBackground Image
RoLYroLLs

3

переконайтеся, що ви встановили зображення для властивості Image, але не для фону


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 без підкласифікації.
Енді Поес

1

Швидкий 5.0

 myButton2.contentMode = .scaleAspectFit
 myButton2.contentHorizontalAlignment = .fill
 myButton2.contentVerticalAlignment = .fill

0

Для Xamarin.iOS (C #):

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

-1

Вам просто потрібно встановити вміст режиму перегляду зображень UIButton на три події. -

[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 під час підкреслення або вибору, якщо розмір кнопки - SQUARE, а розмір зображення - прямокутник, то він буде показувати квадратне зображення під час виділення або вибору.

Я впевнений, що це буде працювати для вас.


Ви не встановлюєте режим вмісту, ви налаштовуєте зображення. І вони не події, це держави. Ти робиш великий безлад. Це абсолютно не пов'язане з питанням.
manecosta
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.