一、前言
最近無意中打開“某品會”的小程式端,發現他們的頭部布局為啥和公司開發的小程式不一樣,自己的隻能文字居中,改變背景色。對方的竟然可以設定2行文字,字型也有大有小,感覺非常的高大上。
某品會小程式首頁:
接下來小編帶着問題去晚上查相關資料,發現微信7.0.0新增了解決不同螢幕頭部問題的終極辦法:
wx.getMenuButtonBoundingClientRect()
有了這個神器支援擷取膠囊按鈕的高度,輕松解決“留海屏” 的适配問題。
二、開發
廢話不多說,直接撸代碼......
1、代碼目錄結構
│
├─components
│ └─navBar
│ navBar.js
│ navBar.json
│ navBar.wxml
│ navBar.wxss
├─pages
│ └─index
│ index.js
│ index.json
│ index.wxml
│ index.wxss
2、代碼片段
components/navBar/navBar.js部分
Component({
options: {
multipleSlots: true,
addGlobalClass: true
},
data: {},
pageLifetimes: {
show: function() {
if (getApp().globalSystemInfo.ios) {
this.getSystemInfo();
this.setStyle(); //設定樣式1
}
},
hide: function() {}
},
methods: {
setStyle: function(life) {
const {
statusBarHeight,
navBarHeight,
capsulePosition,
navBarExtendHeight,
ios,
windowWidth
} = getApp().globalSystemInfo;
const { back, home, title } = this.data;
let rightDistance = windowWidth - capsulePosition.right; //膠囊按鈕右側到螢幕右側的邊距
let leftWidth = windowWidth - capsulePosition.left; //膠囊按鈕左側到螢幕右側的邊距
let navigationbarinnerStyle = [
`color: ${this.data.color}`,
`background: ${this.data.background}`,
`height:${navBarHeight + navBarExtendHeight}px`,
`padding-top:${statusBarHeight}px`,
`padding-right:${leftWidth}px`,
`padding-bottom:${navBarExtendHeight}px`
].join(';');
let navBarLeft = [];
if ((back && !home) || (!back && home)) {
navBarLeft = [`width:${capsulePosition.width}px`, `height:${capsulePosition.height}px`].join(';');
} else if ((back && home) || title) {
navBarLeft = [
`width:${capsulePosition.width}px`,
`height:${capsulePosition.height}px`,
`margin-left:${rightDistance}px`
].join(';');
} else {
navBarLeft = [`width:auto`, `margin-left:0px`].join(';');
}
if (life === 'created') {
this.data = {
navigationbarinnerStyle,
navBarLeft,
navBarHeight,
capsulePosition,
navBarExtendHeight,
ios
};
} else {
this.setData({
navigationbarinnerStyle,
navBarLeft,
navBarHeight,
capsulePosition,
navBarExtendHeight,
ios
});
}
},
_showChange: function(value) {
this.setStyle();
},
// 傳回事件
back: function() {
this.triggerEvent('back', { delta: this.data.delta });
},
home: function() {
this.triggerEvent('home', {});
},
search: function() {
this.triggerEvent('search', {});
},
getSystemInfo() {
var app = getApp();
if (app.globalSystemInfo && !app.globalSystemInfo.ios) {
return app.globalSystemInfo;
} else {
let systemInfo = wx.getSystemInfoSync();
let ios = !!(systemInfo.system.toLowerCase().search('ios') + 1);
let rect;
try {
rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null;
if (rect === null) {
throw 'getMenuButtonBoundingClientRect error';
}
//取值為0的情況 有可能width不為0 top為0的情況
if (!rect.width || !rect.top || !rect.left || !rect.height) {
throw 'getMenuButtonBoundingClientRect error';
}
} catch (error) {
let gap = ''; //膠囊按鈕上下間距 使導航内容居中
let width = 96; //膠囊的寬度
if (systemInfo.platform === 'android') {
gap = 8;
width = 96;
} else if (systemInfo.platform === 'devtools') {
if (ios) {
gap = 5.5; //開發工具中ios手機
} else {
gap = 7.5; //開發工具中android和其他手機
}
} else {
gap = 4;
width = 88;
}
if (!systemInfo.statusBarHeight) {
//開啟wifi的情況下修複statusBarHeight值擷取不到
systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20;
}
rect = {
//擷取不到膠囊資訊就自定義重置一個
bottom: systemInfo.statusBarHeight + gap + 32,
height: 32,
left: systemInfo.windowWidth - width - 10,
right: systemInfo.windowWidth - 10,
top: systemInfo.statusBarHeight + gap,
width: width
};
console.log('error', error);
console.log('rect', rect);
}
let navBarHeight = '';
if (!systemInfo.statusBarHeight) {
systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20;
navBarHeight = (function() {
let gap = rect.top - systemInfo.statusBarHeight;
return 2 * gap + rect.height;
})();
systemInfo.statusBarHeight = 0;
systemInfo.navBarExtendHeight = 0; //下方擴充4像素高度 防止下方邊距太小
} else {
navBarHeight = (function() {
let gap = rect.top - systemInfo.statusBarHeight;
return systemInfo.statusBarHeight + 2 * gap + rect.height;
})();
if (ios) {
systemInfo.navBarExtendHeight = 4; //下方擴充4像素高度 防止下方邊距太小
} else {
systemInfo.navBarExtendHeight = 0;
}
}
systemInfo.navBarHeight = navBarHeight; //導航欄高度不包括statusBarHeight
systemInfo.capsulePosition = rect; //右上角膠囊按鈕資訊bottom: 58 height: 32 left: 317 right: 404 top: 26 width: 87 目前發現在大多機型都是固定值 為防止不一樣是以會使用動态值來計算nav元素大小
systemInfo.ios = ios; //是否ios
app.globalSystemInfo = systemInfo; //将資訊儲存到全局變量中,後邊再用就不用重新異步擷取了
//console.log('systemInfo', systemInfo);
return systemInfo;
}
}
}
});
components/navBar/navBar.wxml部分
<view class="lxy-nav-bar {{extClass}}" style="background: {{backgroundColorTop}};height: {{navBarHeight+ navBarExtendHeight}}px;">
<view class="lxy-nav-bar__placeholder {{ios ? 'ios' : 'android'}}" style="padding-top: {{navBarHeight+ navBarExtendHeight}}px;visibility: hidden;"></view>
<view class="lxy-nav-bar__inner {{ios ? 'ios' : 'android'}}" style="{{navigationbarinnerStyle}}{{displayStyle}}">
<view class='lxy-nav-bar__left' style="{{navBarLeft}}">
<block wx:if="{{back&&!home}}">
<view bindtap="back" class="lxy-nav-bar__button lxy-nav-bar__btn_goback {{iconTheme}}"></view>
</block>
<block wx:if="{{!back&&home}}">
<view bindtap="home" class="lxy-nav-bar__button lxy-nav-bar__btn_gohome {{iconTheme}}"></view>
</block>
<block wx:elif="{{back&&home}}">
<view class="lxy-nav-bar__buttons {{ios ? 'ios' : 'android'}}" wx:if="{{home}}">
<view bindtap="back" class="lxy-nav-bar__button lxy-nav-bar__btn_goback {{iconTheme}}" wx:if="{{back}}"></view>
<view bindtap="home" class="lxy-nav-bar__button lxy-nav-bar__btn_gohome {{iconTheme}}"></view>
</view>
</block>
<block wx:else>
<slot name="left"></slot>
</block>
</view>
<view class='lxy-nav-bar__right'>
<slot name="right"></slot>
</view>
</view>
</view>
pages/index/index.wxml部分
<view class="custom_head" style="height:{{navHeight}}px;">
<view class="flex-row j_b" style="height:{{navObj}}px;padding-top:{{navTop}}px;padding-right:{{navObjWid+5}}px;">
<view class="head_store text_title">
{{store_name}}
</view>
</view>
</view>
pages/index/index.js部分
const app = getApp();
Page({
/**
* 頁面的初始資料
*/
data: {
navHeight: app.globalData.navHeight, //導航欄高度
navTop: app.globalData.navTop, //導航欄距頂部距離
navObj: app.globalData.navObj, //膠囊的高度
navObjWid: app.globalData.navObjWid, //膠囊寬度+距右距離
storeList: [{
name: '品牌特賣 100%正品'
}],
}
}
此處省略樣式部分代碼塊......
三、結果
- 通過微信官方API: getMenuButtonBoundingClientRect(),可以解決各類手機螢幕的适配問題。
- 将算好的參數存儲在全局變量中,隻需一次計算就可以全局使用。