(转载)适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域

适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域

此篇文章是对上一篇文章(http://www.ifiero.com/index.php/archives/611)的进一步补充,主要说明如何适配Apple的最新三款手机iPhoneXs、iPhoneXs Max及iPhoneXr !!!

未适配前:Ball球超过屏幕的上下方
适配后:Ball球就在屏幕的可视范围内运动了

回顾:为何要把场景中的所有图片, 都按照屏幕大小为 2048 * 1536 来绘制。 也就是说, 我们的背景图的大小是 2048 * 1536, 其他图片也是依照这个比例来绘制。

为什么这样做呢?

我们知道 2048 * 1536 是iPad Retina 的分辨率。也是我们需要适配的设备里面分辨率最高的。 所以我们在游戏中都选择了这个大小,让它来兼容分辨率低的设备。 2048 * 1536 在iPad Retina上是完美显示的。 那在其他设备上呢? 先用 AspectFill来进行缩放,并应用相应的屏幕辨率高宽比值Ratio, 来适配各个不同的iPhone尺寸。AspectFill缩放的代码如下:

if let scene = GameScene(fileNamed: "GameScene") {
                scene.size = CGSize(width: 2048, height: 1536)
                scene.scaleMode = .aspectFill /// 缩放
                view.presentScene(scene)
 }

了解了用 AspectFill来进行缩放,那么我们现在就来看看iPhoneX的屏幕尺寸分辨率

以iPhoneX的分辨率为例,SafeArea为安全区域

iPhoneX的屏幕尺寸分辨率(上图中 高度812 = 2436缩小1/3):

设备 屏幕尺寸分辨率 图片存放对应的位置
iPhoneX (1倍 @1x) 375×812 @1x
iPhoneX (2倍 @2x) 750×1624 @2x
iPhoneX (3倍 @3x) 1125×2436 @3x

iPhoneX/iPhoneXs/iPhoneXs Max/iPhoneXr的屏幕尺寸分辨率

iPhoneX系列的分辨率

iPhoneX系列的屏幕分辨率:

设备 屏幕分辨率 图片存放的位置
iPhoneX (3倍 @3x) 1125×2436 @3x
iPhoneXs (3倍 @3x) 1125×2436 @3x
iPhoneXs Max (3倍 @3x) 1242×2688 @3x
iPhoneXr (2倍 @2x) 828×1792 @2x

根据以上iPhoneX系列的屏幕分辨率,得出高宽比Ratio都为2.16

各款iPhone的屏幕分辨比率

橙色整体区域表示我们场景的真实大小, 用 AspectFill来进行缩放后,scene.scaleMode = .aspectFill,黑色线框内的区域表示场景展示在设备上的真实大小(即屏幕可视范围)。

iPad Retina:橙色区域和黑色线框内的区域是完美吻合的,也就是说在设备上能完整显示。

iPhone6/7/8/Plus:黑色线框内的区域是2048 * 1152,这边要注意的是,超出黑色框的内容看不见,设计游戏时,尽量不要把精灵的Position位置放在位于不可见的区域。

iPhoneX:黑色线框内的区域是2048 * 948(兰色为安全区域),其中948高度=2048 / 2.16(高宽比)。

不同尺寸的iPhone的屏幕尺寸比例及屏幕高宽比值

设备 屏幕比例 屏幕高宽比值
iPad Retina 4 / 3 1.33
iPhone 6/7/8 16 / 9 1.77
iPhone 6/7/8 Plus 16 / 9 1.77
iPhone X/Xs/Xr/Xs Max 2.16

再者我们主要是适配SpriteKit游戏开发,因为不需要计算Navigation导航栏的高度,也不需要TabBar状态栏的高度,只需要计算可视区域(屏幕可视范围),还有,注意要把需要交互的元素放在安全区域SafeArea,而不要放在危险区域 Danger Area就行了。

可视区域(屏幕可视范围)= 安全区域 Safe Area + 危险区域 Danger Area

了解了原理后,我们就开始来编写代码吧。

1.extension拓展UIDevice,判断设备是iPhone或者iPhoneX系列或iPad

import UIKit
import SpriteKit

// iPhone X  375*812(H) @1x
// 竖屏
public let AREA_INSET_HEIGHT_TOP   :CGFloat = (UIScreen.main.bounds.height == 812 || UIScreen.main.bounds.height == 896) ? 44.0 : 0
public let AREA_INSET_HEIGHT_BOTTOM:CGFloat = (UIScreen.main.bounds.height == 812 || UIScreen.main.bounds.height == 896) ? 34.0 : 0
// 横屏(安全区域)
public let AREA_INSET_WIDTH_LEFT  :CGFloat = (UIScreen.main.bounds.width == 812 || UIScreen.main.bounds.width == 896) ? 44.0 : 0
public let AREA_INSET_WIDTH_RIGHT :CGFloat = (UIScreen.main.bounds.width == 812 || UIScreen.main.bounds.width == 896) ? 34.0 : 0

extension UIDevice {
    /// 是不是iPhoneX ,如果是竖屏则 UIScreen.main.bounds.height == 812
    public func isPhoneX() -> Bool {
        if UIScreen.main.bounds.width == 812 || UIScreen.main.bounds.width == 896 {  /// 横屏
            return true
        }
        return false
    }
    /// 是不是iPad
    public func isPad() -> Bool {
        return (UIDevice.current.userInterfaceIdiom == .pad) ? true : false;
    }

}

2.检测是哪种设备

  // MARK: - 检测是哪种设备
    func initCheckDevice(){
        if UIDevice.current.isPhoneX() {
            maxAspectRatio = 2.16         /// iPhoneX || iPhoneXs || iPhoneXs Max || iPhoneXr 2.16 高/宽比 ratio
        }else {
            maxAspectRatio  = UIDevice.current.isPad() ? (4.0 / 3.0) : (16.0 / 9.0)  /// iPhone 16:9,iPad 4:3
        }
        /// 画出可视区域
        drawPlayableArea(size: self.size,ratio: maxAspectRatio)
        /// 画出安全区域
        drawSafeArea(size: self.size,ratio: maxAspectRatio)
    }

3.画出安全区域

 // MARK: - 安全区域即用户交互的区域,非可视区域 (iPhoneX的安全区域 < 可视区域)
    func drawSafeArea(size:CGSize,ratio:CGFloat){

        playableHeight  = size.width / ratio
        playableMargin = (size.height - playableHeight ) / 2.0   /// P70

        let safeInsetLeft   =  AREA_INSET_WIDTH_LEFT * ratio
        let safeInsetRight  =  size.width - safeInsetLeft - AREA_INSET_WIDTH_RIGHT * ratio

        playableRect = CGRect(x: safeInsetLeft, y: playableMargin, width:safeInsetRight, height:  playableHeight)  /// 注意 scene的anchorPoint(0,0)原点的位置;
        let shapeFrame = SKShapeNode(rect: playableRect)
        shapeFrame.zPosition = 2
        shapeFrame.strokeColor = SKColor.green
        shapeFrame.lineWidth = 6.0
        addChild(shapeFrame)

    }

4.画出可视区域并赋于可视区域的边届物理特性

 // MARK: - 画出可视区域
    func drawPlayableArea(size:CGSize,ratio:CGFloat){

        playableHeight  = size.width / ratio
        playableMargin = (size.height - playableHeight ) / 2.0   /// P70
        playableRect = CGRect(x: 0, y: playableMargin, width: size.width, height:  playableHeight)  /// 注意 scene的anchorPoint(0,0)原点的位置;
        print("playable Margin",playableMargin)

        let shapeFrame = SKShapeNode(rect: playableRect)
        shapeFrame.zPosition = 1
        shapeFrame.strokeColor = SKColor.red
        shapeFrame.lineWidth = 5.0
        addChild(shapeFrame)

        /// 可视区域的物理状态
        let playableBody = SKPhysicsBody(edgeLoopFrom: playableRect)
        playableBody.friction = 0
        self.physicsBody = playableBody
        playableBody.categoryBitMask    = PhysicsCategory.Frame
        playableBody.contactTestBitMask = PhysicsCategory.Ball
        playableBody.collisionBitMask   = PhysicsCategory.Ball

        /// 地板
        setupFloor()
    }

这样子Ball球就只在可视区域内(屏幕可视范围)运动了。

适配iPhoneXs Max

重要的一点就是要了解屏幕尺寸和安全区域的不同,通俗点讲就是,屏幕可视范围可以放任何元素,但所有的用户交互行为都要放在安全区域内(兰色框内)。

即可视区域(屏幕可视范围)= 安全区域 Safe Area + 危险区域 Danger Area

源码传送门: https://github.com/apiapia/BreakOutGameVansVTutorial

更多游戏教学:http://www.iFIERO.com

分类: SpriteKit, 游戏教程

标签: iPhoneXs适配, iPhoneXR适配, iPhoneXs Max适配

[好文要顶](javascript:void(0);) [关注我](javascript:void(0);) [收藏该文](javascript:void(0);) [
image

](javascript:void(0); "分享至新浪微博") [
image
](javascript:void(0); "分享至微信")
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 周二 热啊。 中午睡得好沉啊,2点钟醒来一次,但是看宿舍的人都还躺着,就继续做梦啦。
    Moerxin阅读 117评论 0 0
  • 姓名:王佳梅 省份:吉林 【日管理打卡第07天】 【知~学习】 1、醒来:知行合一传习读本 2、线上6访、 3、玛...
    王佳梅美容达人阅读 178评论 0 0
  • 坚持目标【读书】分享第655天2018.10.12常见的心理误区 1.家花不如野花香 投资者对成长股往往抱有不切实...
    坚定目标阅读 364评论 0 0
  • 你是否也有过一些想要记起却不敢记起的人?还有一些想要忘记却无法忘记的事? 我有,比如母亲,母亲的离世。 三年半了,...
    玉璃青阅读 510评论 2 1
  • 我们跟孩子在一起的时候,其实就是在有意无意地通过自己的行为和榜样来传递我们的人生价值观,在孩子们十二岁开始反叛之前...
    妈妈在呀阅读 210评论 0 0