如何为iPhone 6/7定制边缘到边缘图像的大小?

说我想要一个捆绑的图像占用一个iPhone应用程序中的所有可用的屏幕宽度 – 例如一个横幅。 我会创build宽度为320px my_banner@2x.png ,宽度为my_banner@2x.png和宽度为my_banner@3x.pngiPhone 6的 1242px 。 但iPhone 6的分辨率是750×1334像素。 它仍然与iPhone 4和5共享@2x后缀,宽度为640px

什么是推荐的方式或指定一个图像文件已被优化的iPhone 6750px像素宽度的好方法 ? 似乎不能在asset catalog ? 应该以编程方式完成吗? 是否有一些可用于iPhone 6的其他后缀?

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

在我看来,很多这些答案想要解决如何限制imageView,我认为你在加载正确的媒体文件? 我会想出我自己的未来可扩展解决scheme,如下所示:

“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 ,在320×640的基础上为2x
  • 在320×568(iPhone 5)的基础上指定4 2x3x图像
  • 为iPhone 6专门创build一个新的图像集(因为这是唯一使边到边绑定有问题的设备)
  • 仅以全分辨率(750×1334)为iPhone 6提供2x图像

声明一个常量

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

这可能不是最美丽的解决scheme,但它起作用,至less只要苹果不提供边缘到边缘绑定的更好的API。

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

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

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

也许苹果将来会开始在图像资产中定位设备的方向?

让我们回到你的问题..解决scheme是用750px宽的图像replace你的@ 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]]; 

我无法find一种方法,因为我有一个背景图像,在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纹理缩放,宽度/高度的比例稍微好一点,所以变化是不明显的。 我希望这给你一些想法,你可以在苹果添加iPhone 6资产之前做什么。

希望这将解决您所有与定制边缘图像相关的问题。
Xcode 6 – 用于通用映像支持的xcassets

确保您使用的是自动布局,然后将所有边缘的检查针脚设置为零,并且不检查针对边距的约束。

你也可以访问这个链接来启动屏幕图像:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions

在这里输入图像描述

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

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

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

  • 沙漠@ 2x :iPhone 4s(320 x 420)
  • 沙漠-568h @ 2x :iPhone 5,5C和5S(320 x 568)
  • 沙漠-667h @ 2x :iPhone 6(375 x 667)
  • desert-736h @ 3x :iPhone 6+(414 x 736)
  • 沙漠@ 2x〜ipad :iPad(1024 x 768)

这种情况没有本地资产支持,所以我认为最好是手动操作,因为处理未logging的文件名可能在未来很容易中断。

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

所以在你的appdelegate有全局的

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

你可以反复打电话 然后检查它们并调用适当的图像

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

在我的情况下,我有兴趣使我的基本视图控制器子类与我的启动图像具有相同的背景图像。

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

此外,即使当我试图创build一个iPhone 6(750×1334)的正确尺寸的背景图像时,将该图像作为图案图像加载到视图的背景颜色中,最终以不希望的方式缩放图像。

这个答案给了我需要为我找出一个好的解决scheme的代码。

这里是我正在努力使我的启动图像匹配我的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")) 

首先,你需要configuration你的imageView来覆盖所有的屏幕, Autolayout将为这个工作提供很多帮助,看看下面的链接,并find如何固定约束(引导空间,尾部空间,顶部空间和底部空间) 使用故事板

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

在这里输入图像描述

第二步是在您的图像资产(下图)上创build设备特定的图像集,根据设备显示不同的图像。

在这里输入图像描述

看看这个图表: http : //www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions

它解释了旧iPhone,iPhone 6和iPhone 6 Plus之间的差异。 您可以看到屏幕尺寸的点,渲染像素和物理像素的比较

就这样

在这里输入图像描述

在这里输入图像描述

如果您有任何问题,请给予反馈。