Как указать размер для индивидуального изображения 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?

размеры экрана iPhone 4,5,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. Вы можете увидеть сравнение размеров экрана в точках, визуализированных и физических пикселях

Это все

Пожалуйста, оставьте отзыв, если у вас возникли проблемы.

Другие вопросы по тегам