Supposons que je souhaite qu'une image fournie occupe toute la largeur d'écran disponible dans une application iPhone, par exemple une bannière. Je créerais my_banner.png
avec largeur 320px
, [email protected]
avec largeur 640px
et [email protected]
pour iPhone 6 plus avec largeur 1242px
. Mais la résolution de iPhone 6 est 750×1334
pixels. Il partage toujours le @2x
suffixe avec les iPhone 4 et 5 qui ont 640px
largeur.
Quelle est la manière recommandée ou une bonne manière de spécifier un fichier image a été optimisé pour le 750px
largeur de iPhone 6? On dirait que cela ne peut pas être fait dans un asset catalog
? Cela devrait-il être fait par programme? Existe-t-il un autre suffixe pouvant être utilisé pour iPhone 6?
(Image extraite de http://www.iphoneresolution.com )
Il me semble que beaucoup de ces réponses veulent savoir comment limiter l'imageView, où je pense que vous êtes préoccupé par le chargement du bon fichier multimédia? Je proposerais ma propre solution extensible future, quelque chose comme ceci:
"UIImage + DeviceSpecificMedia.h" - (une catégorie sur 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
La mise en oeuvre:
#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
J'utilise le truc suivant car certaines choses fonctionnent réellement:
1x
, 2x
sur la base de 320x6404 2x
et 3x
sur la base de 320x568 (iPhone 5)2x
image pour iPhone 6 en pleine résolution (750x1334)Déclarer une constante
#define IS_IPHONE_6 [[UIScreen mainScreen]nativeBounds].size.width == 750.0 ? true : false
et l'utiliser comme ça:
UIImage *image = [UIImage imageNamed:@"Default_Image_Name"];
if(IS_IPHONE_^) {
image = [UIImage imageNamed:@"Iphone6_Image_Name"];
}
ce n'est peut-être pas la plus belle solution, mais cela fonctionne, du moins tant que Apple ne fournit pas une meilleure API pour les liaisons Edge to Edge.
Auto Layout est censé aider à résoudre ce problème.
Maintenant, dites-moi @ Nicklas Berglund, que feriez-vous si l'appareil tournait? Disons que vous êtes maintenant en mode paysage. Comment voulez-vous remplir l'espace horizontal qui n'est plus dans les ressources d'image?
Juste de quoi nourrir vos idées .. La mise en page automatique est censée prendre soin de votre écran, quelle que soit son orientation ou le périphérique sur lequel vous exécutez votre application ..
Peut-être que Apple devrait commencer à cibler les orientations des périphériques dans les ressources d'image à l'avenir?
Revenons à votre question. La solution consiste à remplacer vos images @ 2x par des images de 750 pixels de large, puis de laisser la disposition automatique faire son travail. Oh oui, c'est la partie la plus délicate ..
Si vous ajoutez simplement des contraintes pour l’ajuster, il sera comprimé horizontalement lorsqu’il sera affiché à l’écran de 4 ", mais vous pouvez utiliser des multiplicateurs pour redimensionner l’image de manière appropriée. Voici comment procéder:
[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]];
J'ai posé la même question au support technique de Apple) et ils ont confirmé que cela ne pouvait pas être fait pour une image plein écran dans le catalogue des ressources: "Actuellement, le catalogue des ressources ne dispose d'aucun moyen de charger des périphériques spécifiques. Si votre application doit prendre en charge des images spécifiques à un appareil, vous devez implémenter votre propre code pour détecter la taille de l'écran et choisir l'image appropriée. Vous pouvez déposer une demande d'amélioration en utilisant le lien suivant. Assurez-vous d'expliquer votre cas d'utilisation cette fonctionnalité. "
Je ne pouvais pas trouver un moyen de le faire non plus, car j'avais une image d'arrière-plan parfaitement dimensionnée avec le catalogue des ressources sur tous les appareils, à l'exception de l'iPhone 6. Mon correctif (je l'ai fait dans 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 est l'image d'arrière-plan qui est extraite par le périphérique. S'il s'agit d'un iPhone 6, il ne s'adaptera pas à l'écran et la largeur de l'image d'arrière-plan ne sera donc pas identique à celle de l'écran. Lorsque l'appareil est reconnu en tant qu'iPhone 6, je modifie la texture en la texture R4 (le @ 2x pour la rétine) et la redimensionne aux dimensions correctes.
J'ai essayé de faire la même chose avec l'image @ 2x normale, mais l'image redimensionnée était très mauvaise (elle était trop étendue et trop visible). Avec la texture R4 mise à l'échelle, les proportions largeur/hauteur sont un peu meilleures et le changement n'est même pas perceptible. J'espère que cela vous donne une idée de ce que vous pouvez faire avant Apple ajoute un actif iPhone 6.
J'espère que cela résoudra tous vos problèmes liés à l'image personnalisée Edge to Edge.
Xcode 6 - xcassets pour le support d'image universel
Assurez-vous que si vous utilisez la disposition automatique, vérifiez que pin est défini sur zéro pour toutes les arêtes et que les contraintes de marge ne sont pas cochées.
Vous pouvez également visiter ces liens pour les images de l'écran de lancement:
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
S'il vous plaît essayez cette classe pour changer le nom de l'image par programme.
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
}
}
}
utilisez cette méthode comme ça.
_imgTest.image = UIImage(named: AGTools.fullWidthImage("imageName"))
Il n'y a pas de support natif Assets pour ce cas, donc je pense qu'il serait préférable de le faire manuellement, car le travail avec des noms de fichiers non documentés risque de se rompre facilement à l'avenir.
Il suffit de mesurer les dimensions du périphérique et d’appeler l’image de votre choix. c'est à dire le faire par programmation
Donc, dans votre appdelegate avoir globals
deviceHeight = self.window.frame.size.height;
deviceWidth = self.window.frame.size.width;
que vous pouvez appeler à plusieurs reprises. Puis vérifiez-les et appelez l'image appropriée
if (deviceWidth == 640){
image = IPHONE4IMAGE;
deviceString = @"iPhone4";
}
else...
J'ai vérifié la convention de dénomination d'une image de lancement générée à partir d'un catalogue d'actifs via Xcode 6 et la version paysage pour iPhone 6+, par exemple, avait: LaunchImage-Landscape-736h @ 3x. Png
Sur cette base, je supposerais que ce serait comme suit, pour les dispositifs de rétine, en supposant un fichier de base desert. Png:
Dans mon cas, je souhaitais que ma sous-classe de contrôleur de vue de base ait la même image d’arrière-plan que mon image de lancement.
REMARQUE: Cette approche ne fonctionnera pas à moins que ce ne soit votre besoin spécifique.
De même, même lorsque j'ai essayé de créer une image d'arrière-plan de la taille appropriée pour l'iPhone 6 (750x1334), le chargement de cette image en tant qu'image de motif dans une couleur d'arrière-plan pour une vue finissait par redimensionner l'image de manière indésirable.
Cette réponse m'a donné le code dont j'avais besoin pour trouver une bonne solution pour moi.
Voici le code sur lequel je travaille pour que mon image de lancement corresponde à l'image d'arrière-plan de mon UIViewController
(ou l'inverse):
- (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;
}