Как указать размер для индивидуального изображения iPhone 6/7 от края до края?
Скажем, я хочу, чтобы изображение в комплекте занимало всю доступную ширину экрана в приложении для iPhone - например, баннер. Я бы создал my_banner.png
с шириной 320px
, my_banner@2x.png
с шириной 640px
а также my_banner@3x.png
для iPhone 6 плюс с шириной 1242px
, Но разрешение iPhone 6 750×1334
пиксели. Тем не менее он разделяет @2x
суффикс с iPhone 4 и 5, которые имеют 640px
ширина.
Каков рекомендуемый или хороший способ указать файл изображения, который был оптимизирован для 750px
ширина iPhone 6? Похоже, что это не может быть сделано в asset catalog
? Это должно быть сделано программно? Есть ли какой-нибудь другой суффикс, который можно использовать для iPhone 6?
(Изображение извлечено из http://www.iphoneresolution.com/)
12 ответов
Мне кажется, что многие из этих ответов хотят решить, как ограничить imageView, где я думаю, что вы заинтересованы в загрузке правильного медиа-файла? Я бы придумал свое будущее расширяемое решение, что-то вроде этого:
"UIImage + DeviceSpecificMedia.h" - (категория на UIImage)
Интерфейс:
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, thisDeviceClass) {
thisDeviceClass_iPhone,
thisDeviceClass_iPhoneRetina,
thisDeviceClass_iPhone5,
thisDeviceClass_iPhone6,
thisDeviceClass_iPhone6plus,
// we can add new devices when we become aware of them
thisDeviceClass_iPad,
thisDeviceClass_iPadRetina,
thisDeviceClass_unknown
};
thisDeviceClass currentDeviceClass();
@interface UIImage (DeviceSpecificMedia)
+ (instancetype )imageForDeviceWithName:(NSString *)fileName;
@end
Реализация:
#import "UIImage+DeviceSpecificMedia.h"
thisDeviceClass currentDeviceClass() {
CGFloat greaterPixelDimension = (CGFloat) fmaxf(((float)[[UIScreen mainScreen]bounds].size.height),
((float)[[UIScreen mainScreen]bounds].size.width));
switch ((NSInteger)greaterPixelDimension) {
case 480:
return (( [[UIScreen mainScreen]scale] > 1.0) ? thisDeviceClass_iPhoneRetina : thisDeviceClass_iPhone );
break;
case 568:
return thisDeviceClass_iPhone5;
break;
case 667:
return thisDeviceClass_iPhone6;
break;
case 736:
return thisDeviceClass_iPhone6plus;
break;
case 1024:
return (( [[UIScreen mainScreen]scale] > 1.0) ? thisDeviceClass_iPadRetina : thisDeviceClass_iPad );
break;
default:
return thisDeviceClass_unknown;
break;
}
}
@implementation UIImage (deviceSpecificMedia)
+ (NSString *)magicSuffixForDevice
{
switch (currentDeviceClass()) {
case thisDeviceClass_iPhone:
return @"";
break;
case thisDeviceClass_iPhoneRetina:
return @"@2x";
break;
case thisDeviceClass_iPhone5:
return @"-568h@2x";
break;
case thisDeviceClass_iPhone6:
return @"-667h@2x"; //or some other arbitrary string..
break;
case thisDeviceClass_iPhone6plus:
return @"-736h@3x";
break;
case thisDeviceClass_iPad:
return @"~ipad";
break;
case thisDeviceClass_iPadRetina:
return @"~ipad@2x";
break;
case thisDeviceClass_unknown:
default:
return @"";
break;
}
}
+ (instancetype )imageForDeviceWithName:(NSString *)fileName
{
UIImage *result = nil;
NSString *nameWithSuffix = [fileName stringByAppendingString:[UIImage magicSuffixForDevice]];
result = [UIImage imageNamed:nameWithSuffix];
if (!result) {
result = [UIImage imageNamed:fileName];
}
return result;
}
@end
Я использую следующий трюк, так как некоторые вещи действительно работают:
- Каталог активов для конкретных устройств
- Укажите изображения для
1x
,2x
на базе 320х640 - Укажите изображения для
4 2x
а также3x
на базе 320х568 (iPhone 5) - Создайте новый набор изображений специально для iPhone 6 (так как это единственное устройство, которое создает проблемы с привязками по краям)
- Только предоставить
2x
картинка для iPhone 6 в полном разрешении (750x1334)
Объявить константу
#define IS_IPHONE_6 [[UIScreen mainScreen]nativeBounds].size.width == 750.0 ? true : false
и используйте это так:
UIImage *image = [UIImage imageNamed:@"Default_Image_Name"];
if(IS_IPHONE_^) {
image = [UIImage imageNamed:@"Iphone6_Image_Name"];
}
Возможно, это не самое красивое решение, но оно работает, по крайней мере, до тех пор, пока Apple не предоставляет лучший API для привязки от края к краю.
Auto Layout должен помочь в этой ситуации..
Теперь скажите мне @Nicklas Berglund, что бы вы сделали, если бы устройство вращалось? Допустим, вы сейчас находитесь в ландшафтном режиме. Как бы вы заполнили горизонтальное пространство, которого больше нет в активах изображения?
Просто пища для размышлений... Auto Layout должен заботиться о вашем экране независимо от того, на какой ориентации или на каком устройстве вы запускаете приложение.
Может быть, Apple должна начать ориентироваться на ориентацию устройств в графических ресурсах в будущем?
Давайте вернемся к вашему вопросу. Решение состоит в том, чтобы заменить ваши изображения @2x на изображения шириной 750px, а затем использовать Auto Layout. Ах да, это сложная часть..
Если вы просто добавите ограничения, чтобы подогнать его, он будет сжимать его по горизонтали при отображении на 4-дюймовом экране, но вы можете использовать множители для соответствующего масштабирования изображения. Вот как вы можете это сделать:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[imageFooterView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imageFooterView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[imageFooterView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(imageFooterView)]];
float aspectRatio = imageFooterView.frame.size.height/imageFooterView.frame.size.width;
[imageFooterView addConstraint:[NSLayoutConstraint constraintWithItem:imageFooterView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:imageFooterView attribute:NSLayoutAttributeWidth multiplier:aspectRatio constant:0.0f]];
Я поставил тот же вопрос в службу технической поддержки Apple, и они подтверждают, что для полноэкранного изображения это невозможно сделать в каталоге ресурсов: "В настоящее время у каталога активов нет возможности загружать определенные изображения устройства. Если вашему приложению требуется поддержка устройства Для определенных изображений вам потребуется реализовать собственный код для определения размера экрана и выбора подходящего изображения. Вы можете отправить запрос на улучшение, используя следующую ссылку. Обязательно объясните свой вариант использования этой функции. "
Я также не смог найти способ сделать это, так как у меня было фоновое изображение, идеально подходящее по размеру для каталога устройств на всех устройствах, кроме iPhone 6. Мое исправление (я делал это в SpriteKit)?
if (bgNode.size.width != self.frame.size.width) {
bgNode.texture = [SKTexture textureWithImageNamed:@"i6bg.png"];
[bgNode runAction:[SKAction scaleXTo:self.frame.size.width/bgNode.size.width y:self.frame.size.width/bgNode.size.height duration:.1]];
}
bgNode - это фоновое изображение, отображаемое устройством. Если это iPhone 6, он не помещается на экран, поэтому ширина фонового изображения не будет равна ширине экрана. Когда устройство распознается как iPhone 6, я меняю текстуру на текстуру R4 (@2x для сетчатки) и масштабирую ее до правильных размеров.
Я пытался сделать то же самое с обычным изображением @2x, но масштабированное изображение выглядело очень плохо (оно было слишком растянуто и заметно). С масштабированной текстурой R4 пропорции ширины / высоты немного лучше, и поэтому изменение даже не заметно. Я надеюсь, что это даст вам некоторое представление о том, что вы можете сделать до того, как Apple добавит iPhone 6 Asset.
Надеюсь, что это решит все ваши проблемы, связанные с индивидуальным изображением.
Xcode 6 - xcassets для универсальной поддержки изображений
Убедитесь, что если вы используете автоматическую разметку, проверьте, чтобы вывод был установлен в ноль для всех ребер, а ограничения для полей не проверены.
Вы также можете посетить эти ссылки для изображений экрана запуска:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
В моем случае мне было интересно, чтобы у моего подкласса контроллера базового представления было то же фоновое изображение, что и у моего стартового изображения.
ПРИМЕЧАНИЕ. Этот подход не будет работать, если только это не является вашим конкретным требованием.
Кроме того, даже когда я пытался создать фоновое изображение, которое было подходящего размера для iPhone 6 (750x1334), загрузка этого изображения в качестве изображения шаблона в цвет фона для представления в конечном итоге приводила к нежелательному увеличению изображения.
Этот ответ дал мне код, который мне нужен, чтобы найти хорошее решение для меня.
Вот код, который я получил, чтобы мой стартовый образ совпадал с моим UIViewController
Фоновое изображение (или наоборот):
- (void)viewDidLoad {
[super viewDidLoad];
UIImage *background = [UIImage imageNamed:[self splashImageName]];
UIColor *backgroundColor = [UIColor colorWithPatternImage:background];
self.view.backgroundColor = backgroundColor;
}
- (NSString *)splashImageName {
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGSize viewSize = self.view.bounds.size;
NSString *viewOrientation = @"Portrait";
if (UIDeviceOrientationIsLandscape(orientation)) {
viewSize = CGSizeMake(viewSize.height, viewSize.width);
viewOrientation = @"Landscape";
}
NSArray *imagesDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
for (NSDictionary *dict in imagesDict) {
CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]);
if (CGSizeEqualToSize(imageSize, viewSize) && [viewOrientation isEqualToString:dict[@"UILaunchImageOrientation"]])
return dict[@"UILaunchImageName"];
}
return nil;
}
Просто измерьте размеры устройства и назовите нужное изображение. т.е. делать это программно
Так что в вашем приложении есть глобальные
deviceHeight = self.window.frame.size.height;
deviceWidth = self.window.frame.size.width;
что вы можете позвонить повторно. Затем проверьте их и назовите соответствующее изображение
if (deviceWidth == 640){
image = IPHONE4IMAGE;
deviceString = @"iPhone4";
}
else...
Я проверил соглашение об именах для образа запуска, сгенерированного из каталога ресурсов через Xcode 6, и, например, альбомная версия для iPhone 6+ имела: LaunchImage-Landscape-736h @ 3x.png
Исходя из этого, я бы предположил, что это будет следующим образом для устройств с сетчаткой, предполагая базовый файл desert.png:
- пустыня @ 2x: iPhone 4s (320 х 420)
- desert-568h @ 2x: iPhone 5, 5C и 5S (320 x 568)
- пустыня -667 ч @ 2x: iPhone 6 (375 х 667)
- desert-736h @ 3x: iPhone 6+ (414 x 736)
- пустыня @2x~iPad: iPad (1024 x 768)
В этом случае нет поддержки встроенных ресурсов, поэтому я думаю, что было бы лучше сделать это вручную, так как работа с недокументированными именами файлов может легко сломаться в будущем.
Пожалуйста, попробуйте этот класс, чтобы изменить имя изображения программно.
import UIKit
class AGTools: NSObject {
class func fullWidthImage(imageName: String!) -> String!{
let screenWidth = UIScreen.mainScreen().bounds.size.width
switch (screenWidth){
case 320:
// scale 2x or 1x
return (UIScreen.mainScreen().scale > 1.0) ? "\(imageName)@2x" : imageName
case 375:
return "\(imageName)-375w@2x"
case 414:
return "\(imageName)-414w@3x"
default:
return imageName
}
}
}
используйте этот метод, как это.
_imgTest.image = UIImage(named: AGTools.fullWidthImage("imageName"))
Прежде всего, вам нужно сконфигурировать ваш imageView, чтобы он покрывал весь экран, Autolayout очень поможет в этой работе, взгляните на ссылку ниже и узнайте, как закрепить ограничения (ведущий пробел, конечный пробел, верхний пробел и нижний Пространство) с помощью раскадровки:
http://www.thinkandbuild.it/learn-to-love-auto-layout/
ВТОРОЙ шаг - это создание наборов специфичных для устройства изображений в ваших активах изображений (изображение ниже), чтобы отображать различные изображения в соответствии с устройством.
Проверьте эту инфографику: http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
Это объясняет различия между старыми iPhone, iPhone 6 и iPhone 6 Plus. Вы можете увидеть сравнение размеров экрана в точках, визуализированных и физических пикселях
Это все
Пожалуйста, оставьте отзыв, если у вас возникли проблемы.