Простой способ поместить UIImage в UIButton

У меня есть UIButton в моем приложении для iPhone. Я установил его размер 100x100.

У меня есть изображение размером 400x200, которое я хочу отобразить на кнопке.

Кнопка STILL должна оставаться на уровне 100x100... и я хочу, чтобы изображение уменьшалось, чтобы оно соответствовало... но сохраняйте правильное соотношение сторон.

Я подумал, что для этого используется "Aspect Fit".

Включить ли мое изображение с помощью setImage или setBackgroundImage?

Я устанавливаю AspectFit для кнопки? или изображение? или фоновое изображение?

(Мне нужны меньшие изображения, чтобы УВЕЛИЧИТЬ размер. В то время как большие изображения должны ОПИСАТЬ размер. Всегда держать кнопку в 100x100.)

Я пробовал бесчисленные комбинации всех вышеперечисленных... и я просто не могу получить все, чтобы работать в одно и то же время:

  • Не изменяйте размер кнопки 100x100.
  • Не разрушайте соотношение сторон изображения.
  • Всегда увеличивайте маленькие изображения, чтобы они соответствовали кнопке.
  • Всегда уменьшайте большие изображения, чтобы они соответствовали кнопке.
  • Никогда не зажимайте ни один из краев изображения.
  • Никогда не требуйте взлома "UIButtons over all your UIimages".
  • Не нужно, чтобы все обновлялись до версии 4.1, чтобы использовать новые методы фреймворка.

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

Тьфу.

Ответ 1

UIButton нарушен. Это короткий ответ. Свойства UIImageView в его изображении и backgroundImage не учитывают настройки UIViewContentMode. Они являются свойствами только для чтения, и в то время как содержимое UIImage этих UIImageViews может быть установлено с помощью методов setImage: и setBackgroundImage:, режим содержимого не может быть.

Решение состоит либо в том, чтобы вначале создать нужные изображения в вашем комплекте, либо поместить UIImageView вниз, настроить его так, как вы хотите, а затем наложить на него ясную "пользовательскую" UIButton. Я обещаю, что взломал все эти фантастические профессиональные приложения, которые вы видели. Мы все должны это сделать.

Ответ 2

UIImage *img = [UIImage imageNamed:@"yourImageName"];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[button setImage:img forState:UIControlStateNormal];

Ответ 3

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

Этот (непроверенный) код должен помочь проиллюстрировать, что я имею в виду:

CGSize imageSize = image.size;
CGFloat currentAspect = imageSize.width / imageSize.height;

// for purposes of illustration
CGFloat targetWidth = 100;
CGFloat targetHeight = 100;
CGFloat targetAspect = targetWidth / targetHeight;

CGFloat newWidth, newHeight;

if (currentAspect > targetAspect) {
    // width will end up at 100, height needs to be smaller
    newWidth = targetWidth;
    newHeight = targetWidth / currentAspect;
} else {
    // height will end up at 100, width needs to be smaller
    newHeight = targetHeight;
    newWidth = targetHeight * currentAspect;
}

size_t bytesPerPixel = 4;

// although the image will be resized to { newWidth, newHeight }, it needs
// to be padded with empty space to provide the aspect fit behavior
//
// use calloc() to clear the data as it allocated
void *imageData = calloc(targetWidth * targetHeight, bytesPerPixel);

if (!imageData) {
    // error out
    return;
}

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
if (!colorSpace) {
    // error out
    return;
}

CGContextRef context = CGBitmapContextCreate(
    imageData,
    targetWidth,
    targetHeight,
    8, // bits per component
    targetWidth * bytesPerPixel, // bytes per row
    colorSpace,
    kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst
);

CGColorSpaceRelease(colorSpace);

// now we have a context to draw the original image into
// in doing so, we want to center it, so prepare the geometry
CGRect drawRect = CGRectMake(
    floor((targetWidth - newWidth) / 2),
    floor((targetHeight - newHeight) / 2),
    round(newWidth),
    round(newHeight)
);

CGContextDrawImage(context, drawRect, image.CGImage);

// now that the bitmap context contains the aspect fit image with transparency
// letterboxing, we want to pull out a new image from it
CGImageRef newImage = CGBitmapContextCreateImage(context);

// destroy the temporary context
CGContextRelease(context);
free(imageData);

// and, finally, create a new UIImage
UIImage *newUIImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);

Сообщите мне, если какая-либо часть этого неясно.

Ответ 4

Я думаю, что Дэн пытается сказать (но, не сказав этого), сделать это:

  • Используйте "временное изображение" для изменения размера для вас.
  • Временное изображение должно быть настроено на ASPECT FIT и HIDDEN.
  • Убедитесь, что ваша кнопка настроена на нужный размер и НЕ установлена ​​в ASPECT FIT.
// Make a frame the same size as your button
CGRect aFrame = CGRectMake(0, 0, myButton.frame.size.width, myButton.frame.size.height);

// Set your temp-image to the size of your button
imgTemp.frame = aFrame;

// Put your image into the temp-image
imgTemp.image = anImage;

// Copy that resized temp-image to your button
[myButton setBackgroundImage:tempImage forState:UIControlStateNormal]; 

Ответ 5

Поскольку ни одна из моих попыток не сработала...

Возможно, я должен попросить об этом. При использовании UIButton:

Когда я использую setImage вместо setBackgroundImage? (Почему есть оба?)

Когда я использую "Aspect Fit" вместо "Center"? (Почему обе кажутся растягивать мои изображения, когда я ожидаю, что они будут "сохранять пропорции" и "не изменять размер ничего", соответственно.)

И большой вопрос: почему такая распространенная вещь... такой огромный беспорядок?

Все это будет разрешено, если я найду способ обхода работы: просто используйте UIImage вместо этого и определите TAPS. (Но это, похоже, даже кошмар LARGER кода.)

Apple, если вы попытались упростить мою работу... вместо этого вы сделали это в 400 раз более запутанным.

Ответ 6

Поместите изображение через кнопку, установите изображение для изображения, а не для кнопки.

Все самое лучшее.

Ответ 7

Я бы изменил размер изображения до 100x100, поддерживая соотношение сторон содержимого, содержащегося в изображении. Затем установите для свойства backgroundImage UIButton изображение.

Ответ 8

Я столкнулся с той же проблемой несколько дней назад и решил ее. Пожалуйста, попробуйте с этим

[_profilePicBtn setImage:profilePic forState:UIControlStateNormal];
_profilePicBtn.imageView.contentMode = UIViewContentModeScaleAspectFit;