60

假设我希望捆绑的图像占据 iPhone 应用程序中所有可用的屏幕宽度 - 例如横幅。我会my_banner.png使用 width 320pxmy_banner@2x.pngwidth640pxmy_banner@3x.pngiPhone 6 plus创建width 1242px。但iPhone 6的分辨率是750×1334像素。它仍然@2x与具有640px宽度的 iPhone 4 和 5 共享后缀。

指定已针对iPhone 6的宽度优化的图像文件的推荐方法好方法是什么?似乎它不能在一个?应该以编程方式完成吗?iPhone 6是否有其他后缀?750pxasset catalog

iPhone 4、5、6 屏幕尺寸 (图片摘自http://www.iphoneresolution.com

4

12 回答 12

42

在我看来,很多这些答案都想解决如何约束 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
于 2014-10-31T22:48:37.123 回答
4

我正在使用以下技巧,因为有些东西确实有效:

  • 特定设备的资产目录
  • 1x为,2x在 320x640 的基础上指定图像
  • 在 320x568 (iPhone 5) 的基础上4 2x指定图像3x
  • 专门为 iPhone 6 创建一个新的图像集(因为这是唯一一个在边缘到边缘绑定方面出现问题的设备)
  • 仅提供2x全分辨率 (750x1334) 的 iPhone 6 图像

声明一个常数

#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"];
}

这可能不是最漂亮的解决方案,但它可以工作,至少只要苹果没有为边缘到边缘绑定提供更好的 API。

于 2015-04-22T06:29:07.577 回答
2

自动布局应该有助于解决这种情况..

现在告诉我@Nicklas Berglund 如果设备旋转你会怎么做?假设您现在处于横向模式。您将如何填充不再存在于图像资源中的水平空间?

只是思想的食物..自动布局应该照顾您的屏幕,无论您在哪个方向或在哪个设备上运行您的应用程序..

也许苹果应该在未来开始在图像资产中定位设备方向?

让我们回到你的问题。解决方案是用 750px 宽的图像替换你的 @2x 图像,然后让自动布局完成它的工作。哦,是的,这是棘手的部分..

如果你只是添加约束来适应它,它会在 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]];
于 2014-10-15T14:51:40.110 回答
1

希望这将解决您与自定义边缘到边缘图像相关的所有问题。
Xcode 6 - 通用图像支持的 xcassets

确保如果您使用的是自动布局,则所有边缘的检查引脚都设置为零,并且未选中对边距的约束。

您还可以访问此链接以获取启动屏幕图像: http:
//www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-决议

在此处输入图像描述

于 2014-10-31T15:05:49.180 回答
1

我也找不到解决方法,因为我的背景图像与除 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 资产之前您可以做什么。

于 2014-09-22T04:37:25.283 回答
1

我向苹果技术支持提出了同样的问题,他们确认对于全屏图像无法在资产目录中完成:“目前,资产目录无法加载特定于设备的图像。如果您的应用程序需要支持设备特定的图像,您将需要实现自己的代码来检测屏幕尺寸并选择合适的图像。您可以使用以下链接提交增强请求。请务必说明您使用此功能的用例。“

于 2015-11-13T02:16:37.900 回答
0

就我而言,我有兴趣让我的基本视图控制器子类具有与我的启动图像相同的背景图像。

注意:除非这是您的特定要求,否则此方法将不起作用。

此外,即使我尝试为 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;
}
于 2015-01-24T02:09:38.220 回答
0

只需测量设备尺寸并调用您想要的图像。即以编程方式进行

所以在你的 appdelegate 中有全局变量

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

您可以反复调用。然后检查它们并调用适当的图像

if (deviceWidth == 640){
image = IPHONE4IMAGE;
deviceString = @"iPhone4";
}
else...
于 2014-10-31T16:47:35.473 回答
0

这种情况下没有本机资产支持,所以我认为最好手动完成,因为将来使用未记录的文件名可能会很容易中断。

于 2014-10-27T02:54:09.407 回答
0

我检查了通过 Xcode 6 从资产目录生成的启动图像的命名约定,例如 iPhone 6+ 的横向版本有:LaunchImage-Landscape-736h@3x .png

基于此,我假设对于视网膜设备,假设基本文件沙漠.png如下:

  • 沙漠@2x:iPhone 4s (320 x 420)
  • Desert-568h@2x:iPhone 5、5C 和 5S (320 x 568)
  • Desert-667h@2x : iPhone 6 (375 x 667)
  • Desert-736h@3x : iPhone 6+ (414 x 736)
  • 沙漠@2x~ipad : iPad (1024 x 768)
于 2014-10-10T12:20:59.733 回答
0

请尝试使用此类以编程方式更改图像名称。

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"))
于 2015-09-29T15:58:04.970 回答
-2

首先,您需要配置您的 imageView 以覆盖所有屏幕,自动布局对这项工作有很大帮助,请查看下面的链接并了解如何固定约束(前导空间、尾随空间、顶部空间和底部空间)使用情节提要

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 之间的区别。您可以查看以点、渲染像素和物理像素为单位的屏幕尺寸比较

就这样

在此处输入图像描述

在此处输入图像描述

如果您有任何问题,请提供反馈。

于 2014-10-30T18:07:24.443 回答