ios 如何为 iPhone 6/7 自定义边到边图像指定尺寸?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25892207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to specify size for iPhone 6/7 customised edge-to-edge image?
提问by Niklas Berglund
Say I want a bundled image to take up all available screen width in an iPhone app - for example a banner. I'd create my_banner.png
with width 320px
, [email protected]
with width 640px
and [email protected]
for iPhone 6 pluswith width 1242px
. But the resolution of iPhone 6is 750×1334
pixels. Still it shares the @2x
suffix with iPhone 4 and 5 that have 640px
width.
假设我想要一个捆绑的图像占据 iPhone 应用程序中所有可用的屏幕宽度 - 例如横幅。我会my_banner.png
用 width 320px
、[email protected]
width640px
和[email protected]
为iPhone 6 plus用 width 创建1242px
。但是iPhone 6的分辨率是750×1334
像素。它仍然@2x
与具有640px
宽度的iPhone 4 和 5共享后缀。
What's the recommended wayor a good wayto specify an image file that has been optimised for the 750px
width of iPhone 6? Seems like it cannot be done in an asset catalog
? Should it be done programatically? Is there some other suffix that can be used for iPhone 6?
指定已针对iPhone 6宽度优化的图像文件的推荐方法或好方法是什么?似乎不能在? 它应该以编程方式完成吗?是否有其他后缀可用于iPhone 6?750px
asset catalog
(Image extracted from http://www.iphoneresolution.com)
采纳答案by Jef
It seems to me that a lot of these answers want to address how to constrain the imageView, where I think you are concerned with loading the correct media file? I would come up with my own future extensible solution, something like this:
在我看来,很多这些答案都想解决如何约束 imageView,我认为您关心加载正确的媒体文件?我会想出我自己未来的可扩展解决方案,如下所示:
"UIImage+DeviceSpecificMedia.h" - (a category on UIImage)
“UIImage+DeviceSpecificMedia.h” - (UIImage 上的一个类别)
Interface:
界面:
#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
Implementation:
执行:
#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
回答by Sebastian Flückiger
I am using the following trick as some stuff actually works:
我正在使用以下技巧,因为有些东西确实有效:
- Asset Catalog for specific devices
- Specify images for
1x
,2x
on the base of 320x640 - Specify images for
4 2x
and3x
on the base of 320x568 (iPhone 5) - Create a new Images set for the iPhone 6 specifically (as this is the only device that makes trouble with edge to edge bindings)
- Only provide
2x
image for iPhone 6 in full resolution (750x1334)
- 特定设备的资产目录
- 指定图像
1x
,2x
的320x640的基础上 - 对于指定图像
4 2x
和3x
的320x568的基础上(iPhone 5) - 专门为 iPhone 6 创建一个新的图像集(因为这是唯一一个在边缘到边缘绑定方面出现问题的设备)
- 仅提供
2x
iPhone 6 的全分辨率图像 (750x1334)
Declare a constant
声明一个常量
#define IS_IPHONE_6 [[UIScreen mainScreen]nativeBounds].size.width == 750.0 ? true : false
and use it like this:
并像这样使用它:
UIImage *image = [UIImage imageNamed:@"Default_Image_Name"];
if(IS_IPHONE_^) {
image = [UIImage imageNamed:@"Iphone6_Image_Name"];
}
this might be not the most beautiful solution, but it works, at least as long as apple does not provide a better API for edge to edge bindings.
这可能不是最漂亮的解决方案,但它是有效的,至少只要苹果没有为边缘到边缘绑定提供更好的 API。
回答by Bms270
Auto Layout is supposed to help with this situation..
自动布局应该可以帮助解决这种情况..
Now tell me @Nicklas Berglund what would you do if the device rotates? Lets say you are in landscape mode now.. How would you fill the Horizontal space which is not in the image assets any more?
现在告诉我@Nicklas Berglund 如果设备旋转你会怎么做?假设您现在处于横向模式。您将如何填充不再出现在图像资产中的水平空间?
Just food for thoughts.. Auto Layout supposed to take care of your screen no matter which orientation, or which device you are running your app on..
只是思想的食物.. 自动布局应该照顾你的屏幕,无论你在哪个方向,或者你在哪个设备上运行你的应用程序..
Maybe Apple should start targeting device orientations in image assets in future?
也许苹果将来应该开始在图像资产中定位设备方向?
Lets go back to your question.. The solution is to replace your @2x images with 750px wide images and then have Auto Layout do its job. Oh yea, this is the tricky part..
让我们回到你的问题。解决方案是用 750 像素宽的图像替换你的 @2x 图像,然后让自动布局完成它的工作。哦,是的,这是棘手的部分..
If you just add constraints to fit it, it will squeeze it horizontally when displayed in 4" screen, but you can use multipliers to scale the image appropriately. Here's how you can do it:
如果你只是添加约束来适应它,它会在 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]];
回答by Andriko13
I couldn't find a way to do it either, as I had a background Image that was perfectly sized with the Asset Catalog on every device except the iPhone 6. My fix (I did this in SpriteKit)?
我也找不到方法来做到这一点,因为我有一个背景图像,它的大小与除 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 is the background image that is pulled up by the device. If it's an iPhone 6, it won't fit the screen and so the background image width wont be the same as the screen width. When the device is recognized as an iPhone 6, I change the texture to the R4 texture (the @2x for retina) and scale it to the correct dimensions.
bgNode 是设备拉起的背景图片。如果是 iPhone 6,它将不适合屏幕,因此背景图像宽度不会与屏幕宽度相同。当设备被识别为 iPhone 6 时,我将纹理更改为 R4 纹理(视网膜的 @2x)并将其缩放到正确的尺寸。
I tried doing the same with the regular @2x image, but the scaled image looked very bad (it was too stretched out and noticable). With the R4 texture scaled, the proportions of width/height are a bit better and so the change isn't even noticeable. I hope this gives you some idea as to what you can do before Apple adds an iPhone 6 Asset.
我尝试对常规的 @2x 图像做同样的事情,但缩放后的图像看起来很糟糕(它太拉长了,太明显了)。随着 R4 纹理的缩放,宽/高的比例会好一些,因此变化甚至不明显。我希望这能让您了解在 Apple 添加 iPhone 6 Asset 之前您可以做什么。
回答by Dhaivat Vyas
Hope this will solve all your issues related to customised edge to edge image.
Xcode 6 - xcassets for universal image support
希望这将解决您与自定义边到边图像相关的所有问题。
Xcode 6 - 用于通用图像支持的 xcassets
Make sure if you are using auto layout then check pin is set to zero for all edges and constraints to margin is un checked.
确保如果您使用自动布局,则所有边的检查引脚都设置为零,并且未选中边距约束。
You can also visit this links for launch screen images:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
您还可以访问此链接以获取启动屏幕图像:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-决议
回答by Qiulang
I raised the same question to apple technical support and they confirm that for fullscreen image it can't be done in asset catalog: "Currently, there is no way for the Asset Catalog to load device specific images. If your app needs to support device specific images you will need to implement your own code to detect the screen size and choose the appropriate image. You can file an enhancement request by using the following link. Be sure to explain your use case for this feature. "
我向苹果技术支持提出了同样的问题,他们确认对于全屏图像无法在资产目录中完成:“目前,资产目录无法加载特定于设备的图像。如果您的应用程序需要支持设备您需要实现自己的代码来检测屏幕尺寸并选择合适的图像。您可以使用以下链接提交增强请求。请务必说明您对此功能的使用案例。”
回答by Aspgod
Please try this class to change the image name programmatically.
请尝试使用此类以编程方式更改图像名称。
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
}
}
}
use this method like this.
像这样使用这种方法。
_imgTest.image = UIImage(named: AGTools.fullWidthImage("imageName"))
回答by AMAN77
Just measure the device dimensions and call the image that you want. ie Do it programatically
只需测量设备尺寸并调用您想要的图像。即以编程方式执行
So in your appdelegate have globals
所以在你的 appdelegate 中有全局变量
deviceHeight = self.window.frame.size.height;
deviceWidth = self.window.frame.size.width;
that you can call repeatedly. Then check them and call the appropriate image
您可以重复调用。然后检查它们并调用适当的图像
if (deviceWidth == 640){
image = IPHONE4IMAGE;
deviceString = @"iPhone4";
}
else...
回答by mbm29414
In my case, I was interested in making my base view controller subclass have the same background image as my launch image.
就我而言,我有兴趣让我的基本视图控制器子类具有与我的启动图像相同的背景图像。
NOTE:This approach will not work unless this is your specific requirement.
注意:除非这是您的特定要求,否则此方法将不起作用。
Also, even when I tried creating a background image that was the correct size for the iPhone 6 (750x1334), loading that image as a pattern image into a background color for a view ended up scaling the image up in an undesirable way.
此外,即使当我尝试为 iPhone 6 (750x1334) 创建一个正确大小的背景图像时,将该图像作为图案图像加载到视图的背景颜色中,最终也会以一种不受欢迎的方式放大图像。
This answergave me the code that I needed to figure out a good solution for me.
这个答案为我提供了为我找出一个好的解决方案所需的代码。
Here's the code I got working to have my launch image match my UIViewController
's background image (or vice versa):
这是我用来让我的启动图像与我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;
}
回答by Benzi
I checked the naming convention of a launch image generated from an asset catalog via Xcode 6 and the landscape version for iPhone 6+, for example, had: LaunchImage-Landscape-736h@3x.png
我检查了通过 Xcode 6 从资产目录生成的启动图像的命名约定和 iPhone 6+ 的横向版本,例如:LaunchImage-Landscape-736h@3x.png
Based on that, I'd presume it would be as follows, for retina devices, assuming a base file desert.png:
在此基础上,我假定这将是如下,视网膜设备,假设一个基本文件沙漠巴纽:
- desert@2x: iPhone 4s (320 x 420)
- desert-568h@2x: iPhones 5, 5C and 5S (320 x 568)
- desert-667h@2x: iPhone 6 (375 x 667)
- desert-736h@3x: iPhone 6+ (414 x 736)
- desert@2x~ipad: iPad (1024 x 768)
- 沙漠@2x: iPhone 4s (320 x 420)
- Desert-568h@2x:iPhone 5、5C和 5S (320 x 568)
- 沙漠-667h@2x: iPhone 6 (375 x 667)
- 沙漠-736h@3x:iPhone 6+ (414 x 736)
- 沙漠@2x~ipad: iPad (1024 x 768)