Как указать размер для iPhone 6/7 настраиваемого изображения от края до края?

скажем, я хочу, чтобы связанное изображение занимало всю доступную ширину экрана в приложении iPhone - например, баннер. Я бы создал my_banner.png шириной 320px, my_banner@2x.png шириной 640px и my_banner@3x.png на iPhone 6 plus шириной 1242px. Но разрешение iPhone 6 is 750×1334 пикселей. Тем не менее он разделяет @2x суффикс с iPhone 4 и 5, которые 640px ширина.

что это рекомендуется или хорошее путь чтобы указать файл изображения, который был оптимизирован для 750px ширина iPhone 6? Кажется, это невозможно сделать в asset catalog? Следует ли это делать программно? Есть ли другой суффикс, который можно использовать для iPhone 6?

iPhone 4,5,6 screen sizes (Изображение извлечено из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 на базе 320x640
  • укажите изображения для 4 2x и 3x на базе 320x568 (iPhone 5)
  • создайте новый набор изображений для iPhone 6 специально (так как это единственное устройство, которое создает проблемы с привязками edge to edge)
  • только обеспечить 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 для Привязок edge to edge.


Auto Layout должен помочь в этой ситуации..

теперь скажите мне @Nicklas Berglund что бы вы сделали, если устройство вращается? Допустим, вы находитесь в ландшафтном режиме.. Как бы вы заполнили горизонтальное пространство, которого больше нет в активах изображения?

просто пища для мысли.. Автоматическая компоновка должна заботиться о вашем экране независимо от ориентации или устройства, на котором вы запускаете приложение..

возможно, Apple должна начать таргетинг ориентация устройства в активах изображения в будущем?

вернемся к вашему вопросу.. Решение состоит в том, чтобы заменить ваши изображения @2x широкими изображениями 750px, а затем выполнить автоматическую компоновку. О да, это самая сложная часть..

Если вы просто добавите ограничения, чтобы соответствовать ему, он будет сжимать его по горизонтали при отображении на экране 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]];

Я не мог найти способ сделать это, так как у меня было фоновое изображение, которое было идеально размером с каталогом активов на каждом устройстве, кроме 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 для retina) и масштабировать его до правильных размеров.

Я попытался сделать то же самое с обычным изображением @2x, но масштабированное изображение выглядело очень плохо (оно было слишком растянуто и заметно). При масштабировании текстуры R4 пропорции ширины / высоты немного лучше, поэтому изменение даже не заметно. Я надеюсь, что это даст вам некоторое представление о том, что вы можете сделать, прежде чем Apple добавит актив iPhone 6.


надеюсь, что это решит все ваши проблемы, связанные с настраиваемым изображением edge to edge.
Xcode 6-xcassets для универсальной поддержки изображений

убедитесь, что если вы используете auto layout, то check pin установлен на ноль для всех ребер, а ограничения на маржу не проверяются.

вы также можете посетить эту ссылку для запуска изображений экрана:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions

enter image description here


Я поднял тот же вопрос технической поддержке apple, и они подтверждают, что для полноэкранного изображения это не может быть сделано в каталоге активов: "в настоящее время каталог активов не может загружать определенные изображения устройства. Если ваше приложение должно поддерживать определенные изображения устройства, вам нужно будет реализовать свой собственный код для определения размера экрана и выбрать соответствующее изображение. Запрос на улучшение можно подать по следующей ссылке. Обязательно объясните свой вариант использования этой функции. "


Я проверил соглашение об именах изображения запуска, созданного из каталога активов через Xcode 6, и ландшафтная версия для iPhone 6+, например, имела:LaunchImage-пейзаж-736h@3x.формат PNG

исходя из этого, я бы предположил, что это будет следующим образом, для устройств retina, предполагая базовый файл пустыня.png:

  • пустыня@2x: iPhone 4s (320 x 420)
  • пустыня-568h@2x: iPhones 5, 5C и 5S (320 x 568)
  • пустыня-667h@2x: iPhone 6 (375 x 667)
  • пустыня-736h@3x: iPhone 6+ (414 x 736)
  • пустыня@2х~для iPad: iPad (1024 x 768)

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


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

Итак, в вашем appdelegate есть глобалы

deviceHeight = self.window.frame.size.height;
deviceWidth = self.window.frame.size.width;

что вы можете повторно вызвать. Затем проверьте их и вызовите соответствующее изображение

if (deviceWidth == 640){
image = IPHONE4IMAGE;
deviceString = @"iPhone4";
}
else...

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

Примечание: этот подход не будет работать, если это не ваше конкретное требование.

кроме того, даже когда я попытался создать фоновое изображение, которое было правильным размером для 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;
}

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

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, чтобы покрыть весь экран,режим поможет много для этой работы, посмотрите на ссылку ниже и найдите, как закрепить ограничения (ведущее пространство, конечное пространство, верхнее пространство и нижнее пространство) С помощью раскадровки:

http://www.thinkandbuild.it/learn-to-love-auto-layout/

enter image description here

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

enter image description here

проверьте эту инфографику: http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions

Это объясняет различия между старыми айфонами, iPhone 6 и iPhone 6 Plus. Вы можете увидеть сравнение размеров экрана в точках, отображаемых пикселях и физических пикселях

вот все!--7-->

enter image description here

enter image description here

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