微信小程序适配 iPhone X 总结

jinyongxue 7个月前
   <p>本文主要介绍我们的知识小集小程序在适配 iPhone X 屏幕时遇到的一些问题以及总结,希望对你的小程序开发能有所帮助。</p>    <h2>iPhone X 屏幕数据</h2>    <p>在去年 9 月份 iPhone X 正式发布后,引发了一波 iOS App 适配 iPhone X 的热潮和技术文章,详情可以参考掘金技术社区的这个专题: <a href="/misc/goto?guid=4959758004708426582" rel="nofollow,noindex">《iPhone X 适配实践》</a></p>    <p>我们这里先简单总结一下 iPhone X 屏幕的基础数据,方便后续在小程序开发中进行适配。</p>    <ul>     <li> <p>屏幕尺寸:5.8 英寸(对角线)</p> </li>     <li> <p>屏幕物理分辨率:1125px × 2436px,458 ppi</p> </li>     <li> <p>实际开发适配尺寸:375pt × 812pt,@3x</p> </li>    </ul>    <p>此外,由于在 iPhone X 屏幕顶部状态栏区域有“齐刘海”,以及在屏幕底部增加了“操作条”,如下图所示,因此,我们在开发中需要注意 <strong>安全区域</strong> 的问题。</p>    <p><img src="https://simg.open-open.com/show/6aedc0522628ce6481613ca70ef791ba.png"></p>    <p>根据苹果官方的文档,iPhone X 顶部状态栏的适配安全区域的高度为 44pt,底部操作条区域的高度为 34pt。另外,在 iPhone X 中,一些系统 Bar 的默认高度相比于之前的设备也发生了变化,如下表所示。</p>    <p><img src="https://simg.open-open.com/show/e9bc2e49c03b1fc51df34858b469e0eb.png"></p>    <p>所以在 iOS App 开发中,如果我们使用系统默认的 UINavigationController 和 UITabBarController 时,则无需额外的适配工作,iOS 系统会自动适配好相关 Bar 的安全区域问题。如果我们使用了自定义的导航栏和标签栏,则需要注意根据设备类型区分设置这些 Bar 的不同高度。</p>    <h2>小程序的尺寸单位</h2>    <p>为了解决不同屏幕尺寸的适配问题,小程序自己定了一个尺寸单位:rpx(responsive pixel),它可以根据屏幕宽度进行自适应。小程序中规定, <strong>所有设备的屏幕宽度都为 750rpx</strong> ,根据设备屏幕实际宽度的不同,1rpx 所代表的实际像素值也不一样。</p>    <p>根据 <a href="/misc/goto?guid=4959758004807356677" rel="nofollow,noindex">微信开发文档</a> ,在 4.7 英寸的 iPhone 设备上(iPhone 6/7/8),屏幕宽度为 375px(此处应该理解为 375 point),共有 750 个物理像素,则 750rpx = 375px = 750 物理像素,1rpx = 0.5px = 1物理像素。</p>    <p><img src="https://simg.open-open.com/show/250a3046f1e08f945b0590d8306967ed.png"></p>    <h2>小程序中如何判断设备为 iPhone X</h2>    <p>上面我们简要介绍了 iPhone X 的屏幕数据和小程序中的尺寸单位作为铺垫,现在终于要切入正题了,要在小程序中适配 iPhone X 屏幕,首先我们需要知道如何判断设备类型。</p>    <p>微信的小程序 API 中提供了一个 wx.getSystemInfo(OBJECT) 方法用于获取用户手机的系统信息和设备信息,包含如下数据:</p>    <p><img src="https://simg.open-open.com/show/2c7ef2ecd60388ce588f1d824bf5da6f.png"></p>    <p>上述每个字段的含义详见 <a href="/misc/goto?guid=4959758004888698224" rel="nofollow,noindex">文档</a> ,我们不再一一赘述。</p>    <p>因此,我们可以根据该方法返回的手机型号字段 model 是否包含 iPhone X 字符串来判断设备是否为 iPhone X,也可以根据 screenHeight 的高度是否等于 812 来判断。</p>    <p>NOTE:这里有一个小坑需要注意,在微信开发者工具中的模拟器,如果选择为 iPhone X,此时获取到的 model 值为 iPhone X ,导致我以为真机也是这个值,于是直接用 if (model == 'iPhone X') 来判断,但其实真机下 model 的值为这种格式: iPhone X (GSM+CDMA)<iPhone10,3> ,因此我们需要用字符串检索匹配进行判断。</p>    <p>综上,我们可以在 app.js 的 globalData 中添加一个字段 isIPX 用于标识当前设备是否为 iPhone X,然后在小程序启动时 onLaunch 中调用 wx.getSystemInfo(OBJECT) 方法并在其 success 回调中读取 model 字段进行分析,代码大致如下:</p>    <pre>  <code class="language-javascript">App({    // 全局数据    globalData: {      // 其他数据定义 ...            isIPX: false, // 当前设备是否为 iPhone X    },        // 小程序启动入口    onLaunch: function (options) {      // 其他启动代码...            // 判断设备是否为 iPhone X      this.checkIsIPhoneX()    },        checkIsIPhoneX: function() {      const self = this      wx.getSystemInfo({        success: function (res) {          // 根据 model 进行判断          if (res.model.search('iPhone X') != -1) {            self.globalData.isIPX = true          }          // 或者根据 screenHeight 进行判断          // if (res.screenHeight == 812) {          //   self.globalData.isIPX = true          // }        }      })    },  }  </code></pre>    <p>如果需要小程序启动时立即获取设备相关信息,也可以调 wx.getSystemInfoSync() 方法,它会同步获取数据并立即返回。</p>    <h2>页面适配实战</h2>    <p>在小程序页面开发中,涉及到需要适配 iPhone X 的地方主要有:导航栏(NavigationBar),标签栏(TabBar)以及页面底部的吸底按钮。</p>    <ul>     <li>导航栏和标签栏适配</li>    </ul>    <p>如果我们使用微信小程序官方组件进行开发,没有进行自定义,在 app.json 文件中设置 tabBar 页面,且 window 的 navigationStyle 值为 default ,那么我们无需在 iPhone X 中对导航栏和标签栏进行适配,微信会自动帮我们适配好,如下图为知识小集小程序的首页:</p>    <p><img src="https://simg.open-open.com/show/fd92bbd6e436112f656f510e110c7c1a.png"></p>    <p>但是我们如果是自定义导航栏(在 app.json 文件中设置 window 的 navigationStyle 为 custom ,此时只保留右上角胶囊状的按钮,需要开发者自己画导航栏样式)和标签栏,则我们需要在每个页面中判断设备类型,并针对 iPhone X 屏幕在安全区域内进行布局,并修改相关 Bar 的高度值(见上述表格)。</p>    <p>以自定义导航栏适配为例,步骤如下:</p>    <p>(1)在每个页面的 page.js 中先读取 app.js 中的 isIPX 值,如下:</p>    <pre>  <code class="language-javascript">const app = getApp()    Page({    data: {      // 页面其他数据...            isIPX: app.globalData.isIPX,    },        // 其他代码  }  </code></pre>    <p>(2)然后在 page.wxss 样式文件中对某一个视图 View 分别为普通屏幕和 iPhone X 屏幕写两种样式,如下:</p>    <pre>  <code class="language-javascript">.navi-bar-view {    height: 64px;    /* 其他样式值 */  }  .navi-bar-view-IPX {    height: 88px;    /* 其他样式值 */  }  </code></pre>    <p>(3)最后在 page.wxml 页面结构布局中根据 isIPX 的值给 View 设置不同的 class 样式,如下:</p>    <pre>  <code class="language-javascript"><view class="{{isIPX ? 'navi-bar-view-IPX' : 'navi-bar-view'}}">  </view>  </code></pre>    <p>此外,对于自定义导航栏和标签栏,我建议还是要遵循 iPhone UI 的设计规范,样式可以参考苹果官方的渲染图:</p>    <p><img src="https://simg.open-open.com/show/752934276a701d5d1a2c7ca128b56746.png"></p>    <ul>     <li>吸底按钮适配</li>    </ul>    <p>在小程序页面中,吸底按钮是很常见的一种设计,我们一般会把一些重要的按钮放在页面底部悬浮不动,例如我们知识小集小程序的“小集详情页”底部的“收藏”和“转发”按钮:</p>    <p><img src="https://simg.open-open.com/show/1ad82e3832425189cf9913c0cf67aa2f.png"></p>    <p>在 iPhone X 中我们需要把吸底按钮往上偏移 34 像素,可通过在 CSS 样式中设置 padding-bottom 为 34px 实现,参考代码如下:</p>    <pre>  <code class="language-javascript">.feed-bottom-view {    width: 100%;    height: 48px; /* 吸底按钮的高度 */    bottom: 0;    opacity: 0.95;    position: fixed;    border-top-style: solid;    border-top-width: 0.5px; /* 分割线的高度 */    border-color: lightgrey;    background-color: #F8F8F8;  }  .feed-bottom-view-IPX {    /* iPhone X 内容往上偏移 34px */    padding-bottom: 34px;  }  </code></pre>    <pre>  <code class="language-javascript"><view class="{{isIPX ? 'feed-bottom-view feed-bottom-view-IPX' : 'feed-bottom-view'}}">  <!-- 底部吸底按区域 -->  </view>  </code></pre>    <p>备注:如前面所述,对于不同设备宽度,1rpx 所代表的实际像素值也不一样,而在不同尺寸的 iPhone 设备(3.5/4.0/4.7/5.5 英寸)中,虽然它们的宽度不同,但其导航栏+状态栏的高度都为 64pt(iPhone X 为 88pt),标签栏 TabBar 的高度都为 49pt(iPhone X 为 83pt)。所以在小程序开发中,当我们需要自定义导航栏、标签栏,或者适配 iPhone X 顶部和底部安全区域时,我建议此处的单位直接使用 px (在小程序中对应 iOS 开发中的点 pt )而不使用 rpx (当然页面的其他元素的尺寸描述还是推荐使用 rpx ),以确保最终渲染显示的高度与 iOS 系统默认的一致。</p>    <h2>总结</h2>    <p>本文简要介绍了在小程序开发中如何适配 iPhone X 屏幕,更多细节请查阅我们在 GitHub 上开源的知识小集小程序的代码: <a href="/misc/goto?guid=4959758004974470324" rel="nofollow,noindex">awesome-tips-wx-app</a></p>    <p> </p>    <p>来自:https://kangzubin.com/wxapp-iphonex/</p>    <p> </p>