微信小程序适配iPhoneX及后续型号底部小黑条(底部安全区域)

适配问题

自 iPhone X 开始,底部增加了小黑条,也就是安全区域,微信小程序官方已经针对 iPhoneX 及后续型号的底部小黑条做了适配,小程序底部的 tabbar 不会被黑条遮挡,但是其他页面自定义的底部导航,还需要我们自己来解决。

先看效果图

解决方案

大概的解决方案是根据不同手机型号,判断是否需要增加CSS样式,然后利用 padding-bottom 或 height 来处理导航的位置。

相关代码

1. 判断手机型号

在 app.js 的 onLaunch 函数内调用 wx.getSystemInfo 获得手机型号,并存储为全局变量:

onLaunch: function() {
	var _this = this;

	//Yangjunwei-5839:iPhoneX及以后型号适配底部黑线问题 S
	//var sdkVersion = wx.getSystemInfoSync().SDKVersion; //从基础库 2.20.1 开始,本接口停止维护,请使用 wx.getAppBaseInfo 代替
	var sdkVersion = wx.getAppBaseInfo().SDKVersion; //基础库版本不低于 2.21.3
	console.log("app.js / sdkVersion 基础库: ", sdkVersion);
	if( _this.compareVersion(sdkVersion, '2.21.3') >= 0 ){
		var deviceInfo = wx.getDeviceInfo();
		var deviceModel = deviceInfo.model;
		console.log("app.js / wx.getDeviceInfo: ", deviceInfo);

		//查询设备型号是否包含如下几个型号,包含则注明,可在后续添加CSS样式
		if( deviceModel.search('iPhone X') != -1 ){
			_this.setCache("isIpx", deviceModel);
		}
		else if( deviceModel.search('iPhone 11') != -1 ){
			_this.setCache("isIpx", deviceModel);
		}
		else if( deviceModel.search('iPhone 12') != -1 ){
			_this.setCache("isIpx", deviceModel);
		}
		else if( deviceModel.search('iPhone 13') != -1 ){
			_this.setCache("isIpx", deviceModel);
		}
		else if( deviceModel.search('iPhone 14') != -1 ){
			_this.setCache("isIpx", deviceModel);
		}
		else if( deviceModel.search('iPhone 15') != -1 ){
			_this.setCache("isIpx", deviceModel);
		}
		else{
			_this.setCache("isIpx", "");
		}
	}
	else{
		wx.getSystemInfo({
			success: function(t) {
				console.log("app.js / wx.getSystemInfo: ", t);
				"0" == t.model.indexOf("iPhone X") ? _this.setCache("isIpx", t.model) : _this.setCache("isIpx", "");
			}
		});
	}
	//Yangjunwei-5839:iPhoneX及以后型号适配底部黑线问题 E

	…………
},

//小程序基础库版本比较
compareVersion: function(e, n) {
	e = e.split("."),
	n = n.split(".");
	for (var o = Math.max(e.length, n.length); e.length < o; ) e.push("0");
	for (;n.length < o; ) n.push("0");
	for (var s = 0; s < o; s++) {
		var t = parseInt(e[s]), i = parseInt(n[s]);
		if (t > i) return 1;
		if (t < i) return -1;
	}
	return 0;
},

getCache: function(e, t) {
	var a = +new Date() / 1e3, i = "";
	a = parseInt(a);
	try {
		(i = wx.getStorageSync(e + this.globalData.appid)).expire > a || 0 == i.expire ? i = i.value : (i = "", 
		this.removeCache(e));
	} catch (e) {
		i = void 0 === t ? "" : t;
	}
	
	return i = i || "";
},
setCache: function(e, t, a) {
	var i = +new Date() / 1e3, n = !0, o = {
		expire: a ? i + parseInt(a) : 0,
		value: t
	};
	try {
		wx.setStorageSync(e + this.globalData.appid, o);
	} catch (e) {
		n = !1;
	}
	return n;
},

2. 所需页面根据型号调用CSS样式

在所需页面的 .js 文件的 onLoad 或 onShow 函数内,根据上一步的全局变量 isIpx 存储的手机型号值,判断自定义底部导航是否需要调用 CSS 样式,样式名为 fui-iphonex-navbar

var o = getApp();

onLoad: function() {
	if( app.getCache("isIpx") ){
		this.setData({
			iphonexnavbar: "fui-iphonex-navbar"
		})
	}
}

onShow: function () {
	if( app.getCache("isIpx") ){
		this.setData({
			iphonexnavbar: "fui-iphonex-navbar"
		})
	}
}

在所需页面的 .wxml 文件中,添加样式 {{iphonexnavbar}}


3. 添加CSS样式

在 app.wxss 中新增如下代码

/*Yangjunwei-5839: 防止苹果手机底部小黑条遮挡 2024.05.07 S*/
.fui-iphonex-navbar{ bottom:68rpx !important; }
/*Yangjunwei-5839: E*/

拓展一下

可以利用 iOS 新增的 “viewport-fit” 特性或 “env() 和 constant()” 特性,结合 iPhone 各种设备尺寸及数据表来实现。

官方文档:https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/