微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

Owenooooo發表於2018-11-16

首發帖, 若有不足或錯誤或更優的方式,請指出,感謝

假設場景

當使用者進入小程式之後, 需要在獲取到頭像暱稱等相關資訊授權之後才允許他進行其它互動操作;

由於微信小程式升級之後, 直接呼叫 wx.authorize({scope: "scope.userInfo"}),無法再彈出授權視窗;

需要變相使用 <button open-type="getUserInfo"/>來引導使用者進行基本資訊授權操作,

如自定義帶遮蓋層的對話方塊來引導使用者授權資訊, 如這樣(請自動忽略打碼部分)

微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

圖中的確定按鈕,即為 <button open-type="getUserInfo"/>, 點選後為下圖

微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

實現思路

我們知道, 微信小程式原生的tabbar只提供了wx.hideTabBar wx.showTabBar來控制其隱藏或顯示, 而原生tabbar的層級總是在最頂層, 若tabbar處於顯示狀態, 那麼自定義的遮蓋層是無法遮擋擋它的

因此我的想法是用wx.hideTabBar在app的onLauch中先隱藏掉tabbar導航欄, 再使用一張與導航欄相同的圖片佔用導航欄的空位, 並置於遮蓋層下層層級, 且隨著遮蓋層一起顯示與隱藏

實現要點

剛開始,我以為直接把佔位的tabbar圖片fixed後設定bottom為0就可以解決了, 雖然開發工具上沒有任何問題, 但是真機效果是這樣(iphone X):

微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

也就是說,真機中tabbar的位置並非是位於整個頁面的最底部

於是我換了一種思路,通過微信小程式的wepy.getSystemInfoSync()來獲取螢幕實際高度screenHeight, 通過 query.select('#fake-tabbar').boundingClientRect();query.exec(function(res) {}) 來獲得之前設定高度為xx rpx的tabbar圖片所在節點實際渲染出的高度; 兩者相減後的差值,即為動態設定的佔位tabbar圖片的top值;

需要注意的地方: 佔位tabbar 圖片應該為兩張, 一張為底圖,一張為tabbar圖, 如下:

微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

底圖位置與tabbar圖的位置一致並位於它的下方, 為防止遇上像iphoneX 這樣的長屏手機底端因tabbar高度不夠出現縫隙, 故打底的這張背景圖的高度稍微設定高一些

全部程式碼

使用的wepy, 直接寫成了一個元件

<style lang="less" scoped>
/* 授權彈窗 */
.authorize_alert_wrapper {
  .cover {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    background-color: #000000;
    opacity: 0.6;
    z-index: 110;
  }
  .authorize_alert {
    width: 506rpx;
    height: 232rpx;
    box-sizing: border-box;
    padding-top: 40rpx;
    background: #ffffff;
    border-radius: 16rpx;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    overflow: hidden;
    z-index: 120;
    .authorize_alert_describe {
      font-family: 'PingFangSC-Regular', 'Microsoft Yahei', sans-serif;
      font-size: 32rpx;
      color: #333333;
      letter-spacing: 0;
      text-align: center;
      margin-top: 18rpx;
    }
    .confirm_cancel {
      position: absolute;
      width: 506rpx;
      height: 72rpx;
      box-sizing: border-box;
      bottom: 0;
      left: 0;
      .confirm {
        width: 100%;
        height: 72rpx;
        line-height: 72rpx;
        padding: 0;
        margin: 0;
        text-align: center;
        font-size: 32rpx;
        color: #999;
        border: none;
        border-radius: 0;
        border-top: 2rpx solid #e1e1e2;
        background-color: #fff;
        font-family: 'PingFangSC-Regular', 'Microsoft Yahei', sans-serif;
        float: right;
        letter-spacing: 1px;
        color: #21b922;
        &:after {
          border-radius: 0;
          border: none;
        }
      }
      .confirm_hover {
        background-color: #eee;
      }
    }
  }
}
.pre-fake-tabbar, .pre-fake-tabbar-bg {
  width: 100%;
  height: 96rpx;
  position: fixed;
  left: 0;
}

.pre-fake-tabbar-bg {
  height: 150rpx;
}

.show {
  opacity: 1;
}

.hide {
  opacity: 0;
}

</style>
<template>
<!-- 使用 wx.getUserInfo從2018年4月30日開始,小程式與小遊戲的體驗版、開發版呼叫 wx.getUserInfo 介面,將無法彈出授權詢問框,預設呼叫失敗, 以下為變通辦法-->
    <view class="authorize_alert_wrapper {{showModal ? 'show' : 'hide'}}"  @touchmove.stop="catchTouchEvent">
        <image id="fake-tabbar_bg" class="pre-fake-tabbar-bg" src="{{fakeTabbarBgUrl}}" style="top:{{fakeTabbarTop}};"/>        
        <image id="fake-tabbar" class="pre-fake-tabbar" src="{{fakeTabbarUrl}}" style="top:{{fakeTabbarTop}};"/>
        <view id="cover" class='cover'></view>
        <view class="authorize_alert">
            <view class="authorize_alert_describe">前往授權才能繼續操作</view>
            <view class="confirm_cancel">
                <button class="confirm" hover-class="confirm_hover" @tap.stop="tap" data-btn-type="confirm" open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="onGotUserInfo">
                    確定
                </button>
            </view>
        </view>
    </view>
</template>
<script>
import wepy from 'wepy';
const app = wepy.$instance;
export default class AuthModal extends wepy.component {
  data = {
    showModal: false,
    fakeTabbarUrl: '../images/index/fake_tabbar.png',
    fakeTabbarBgUrl: '../images/index/fake_tabbar_bg.png',
    fakeTabbarTop: null
  };
  methods = {
    tap() {
      this.hide();
    },

    onGotUserInfo(e) {
      const self = this;
      console.log('授權', e);
      if (e.detail.userInfo) {
        //授權成功
        console.log('授權成功', e);
        app.globalData.wxUserInfo = e.detail.userInfo;
        self.$apply();
        //通知主介面更新使用者訊息
        self.$emit('userinfo-update', e.detail.userInfo);
      } else {
        self.show();
      }
    },

    catchTouchEvent() {
      console.log('阻止觸控穿透')
    }
  };

  hide() {
    this.showModal = false;
    this.$apply();
    wepy.showTabBar();
  }

  show() {
    this.showModal = true;
    this.$apply();
    wepy.hideTabBar();
  }

  autoAdjustTabTop() {
    const res = wepy.getSystemInfoSync();
    const {screenHeight} = res;
    const self = this;
    const query = wepy.createSelectorQuery();
    query.select('#fake-tabbar').boundingClientRect();
    query.exec(function(res) {
      console.log('boundingClientRect', res);
      const resData = res[0];
      // 獲取全屏的高度 獲取fake-tabbar的實際高度 計算fake-tabbar距離頂端的真實距離
      const fakeTabbarTop = screenHeight- res[0].height;
      console.log('fakeTabbarTop', fakeTabbarTop)
      self.$apply();
    });
  }

  onLoad() {
    this.autoAdjustTabTop();
  }
}
</script>

複製程式碼

探討

小程式原生tabbar的高度因手機型號不同而發生改變, 但是微信小程式官方卻並沒有給出一個可獲取tabbar高度的API, 這也使得在使用tabbar圖片進行佔位的效果與真實tabbar顯示之後的實際效果有所差異

微信小程式-騷操作,自定義授權對話方塊,且遮蓋層遮住tabBar

是否有更優的方法來產生遮蓋層遮蓋住tabbar導航欄的效果, 並使使用者不會察覺到?
或者又有什麼方法來使自定義tabbar的高度相容性更好更接近原生的顯示效果?

期待能得到更多解決方案

相關文章