web-dev-qa-db-ja.com

iPhone 6/7のカスタマイズされたEdge-to-Edgeイメージのサイズを指定する方法

たとえば、バナー画像など、iPhoneアプリで利用可能なすべての画面幅をバンドル画像で占めたいとします。 my_banner.pngを作成し、320px[email protected]幅を640pxおよび[email protected] foriPhone 6 pluswith幅1242px。ただし、iPhone 6の解像度は750×1334ピクセルです。それでも、@2xのサフィックスは、640px幅のiPhone 4および5と共有します。

推奨方法または良い方法とは750pxiPhone 6用に最適化されていますか? asset catalogではできないようです。プログラムで行う必要がありますか? iPhone 6に使用できる他のサフィックスはありますか?

iPhone 4,5,6 screen sizes ( http://www.iphoneresolution.com から抽出した画像

60
Niklas Berglund

これらの答えの多くは、正しいメディアファイルのロードに関心があると思われる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
43
Jef

いくつかのものが実際に機能するため、次のトリックを使用しています。

  • 特定のデバイスの資産カタログ
  • 320x640のベースで1x2xの画像を指定します
  • 320x568(iPhone 5)のベースで4 2xおよび3xの画像を指定します
  • 特にiPhone 6用の新しい画像セットを作成します(これがEdge to Edgeバインディングで問題を起こす唯一のデバイスであるため)
  • IPhone 6のフル解像度(750x1334)の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"];
}

これは最も美しいソリューションではないかもしれませんが、少なくともAppleがEdge to Edgeバインディングのためのより良いAPIを提供しない限り、動作します。

自動レイアウトはこの状況に役立つはずです。

では、@ 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]];
2
Bms270

同じ質問をAppleテクニカルサポートに提起しましたが、フルスクリーンイメージではアセットカタログで実行できないことを確認しています。「現在、アセットカタログがデバイス固有のイメージをロードする方法はありません。アプリはデバイス固有の画像をサポートする必要があります。独自のコードを実装して画面サイズを検出し、適切な画像を選択する必要があります。次のリンクを使用して機能強化リクエストを提出できます。この機能のユースケースを必ず説明してください」

1
Qiulang

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アセットを追加する前に何ができるかについてのアイデアが得られることを願っています。

1
Andriko13

これにより、カスタマイズされたEdge to Edgeイメージに関連するすべての問題が解決されることを願っています。
Xcode 6-ユニバーサルイメージサポート用のxcassets

自動レイアウトを使用している場合は、すべてのエッジでピンがゼロに設定され、マージンの制約がオフになっていることを確認してください。

起動画面の画像については、次のリンクもご覧ください。
http://www.paintcodeapp.com/news/iphone-6-screens-demystified
http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions

enter image description here

1
Dhaivat Vyas

このクラスを試して、プログラムでイメージ名を変更してください。

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"))
0
Aspgod

この場合のネイティブAssetsのサポートはないため、ドキュメント化されていないファイル名での作業は将来簡単に中断される可能性があるため、手動で行うことをお勧めします。

0
Rivera

デバイスの寸法を測定し、必要な画像を呼び出すだけです。すなわち、プログラムで行う

あなたの代理人にはグローバルがあります

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

繰り返し呼び出すことができます。次に、それらを確認し、適切な画像を呼び出します

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

Xcode 6を介してアセットカタログから生成された起動画像の命名規則と、iPhone 6以降のランドスケープバージョンを確認しました。たとえば、LaunchImage-Landscape-736h @ 3x。png

それに基づいて、ベースファイルdesert。pngを想定したRetinaデバイスの場合、次のようになると思います。

  • desert @ 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)
  • desert @ 2x〜ipad:iPad(1024 x 768)
0
Benzi

私の場合、ベースビューコントローラーのサブクラスに起動画像と同じ背景画像を持たせることに興味がありました。

注:このアプローチは、これが特定の要件でない限り機能しません。

また、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;
}
0
mbm29414