小程序 swiper 如何多頁面高度自適應(yīng)

輪播诱告,這個概念只要做過 UI 的都不會陌生藻雪,盲猜市場上 90% 的應(yīng)用都有這個需求万搔,在 iOS 和 Android 上都有很完善的控件蘸嘶,比如 Android 的 ViewPager 和 iOS 的 UIScrollview。

小程序這么牛逼计雌,肯定也要有控件支持這個特性啊悄晃, swiper 就這么誕生了。

但是 swiper 有一個很嚴(yán)重的問題凿滤,就是高度默認(rèn) 150px妈橄,且不可以自適應(yīng)內(nèi)容調(diào)整高度庶近。

這就有問題了,我現(xiàn)在有一個多 Tab 的頁面眷蚓,最少高度要滿屏鼻种,還要超出內(nèi)容可以往下滾動,此時就蒙蔽了溪椎,怎么給 swiper 設(shè)置高度呢普舆?

首先看一下我搜索到的一些方法:

  1. 在初始化的時候獲取到屏幕的高度,然后將高度設(shè)置到 swiper 上校读,至于滾動的問題沼侣,在里面再嵌入一個 scroll-view

    這個問題有很多坑,首先 屏幕的高度要比內(nèi)容區(qū)的高度大歉秫,這么設(shè)置以后就算內(nèi)容較少蛾洛,頁面也能滑動一點;其次雁芙,小程序的 scroll-view 在實現(xiàn)上拉加載更多的時候轧膘,坑更多。

  2. 每個 item 的高度都一致兔甘,根據(jù) item 的數(shù)量和統(tǒng)一的高度計算出內(nèi)容的高度谎碍,然后設(shè)置進(jìn)去

    這個方案感覺完全是 zz 方案,局限性太大了

我的方案

一句話解釋:給 swiper-item 內(nèi)部添加三個錨點洞焙,最上面一個蟆淀,最下面一個,還有一個錨點始終位于屏幕最底下澡匪。根據(jù)這三個錨點計算出內(nèi)容高度和內(nèi)容顯示區(qū)高度熔任。
PS:錨點,寬高為 0 的不可見的 view唁情,用于獲取定位

如果還有不理解可以看下面這個示意圖:

image

這三個錨點的具體作用是用來計算 swiper 內(nèi)容高度和 swiper 距離屏幕底部的具體疑苔,計算方式如下:

  1. 使用 swiper-item 內(nèi)部的兩個錨點計算出內(nèi)容區(qū)高度
  2. 通過屏幕底部和 swiper-item 頂部的錨點計算出離屏幕底部的距離

接下來看看代碼具體實現(xiàn)

代碼實現(xiàn)

page.wxml

<view>
    <swiper style="height: {{anchor.deviceHeight + 'px'}}">
        <swiper-item>
            <view class="anchor-top"></view>
            <!-- 你的內(nèi)容 -->
            <view class="anchor-bottom"></view>
        </swiper-item>
    </swiper>
    <view class="anchor-screen-bottom"></view>
</view>

page.wxss

.anchor-top {
    width: 0;
    height: 0;
}

.anchor-bottom {
    width: 0;
    height: 0;
}

.anchor-screen-bottom {
    position: absolute;
    bottom: 0;
    width: 0;
    height: 0;
}

page.js

Page({
    data: {
        anchor: {
            deviceHeight: 0,
      anchorTop: 0,
      anchorBottom: 0,
      anchorScreenBottom: 0
        }
    },
    onReady: function() {
        this.computeSwiperHeight(0)
    },
    computeSwiperHeight(pageIndex) {
      let getSwiperHeight = () => {
      let min = this.data.anchor.anchorScreenBottom - this.data.anchor.anchorTop;
      let value = this.data.anchor.anchorBottom - this.data.anchor.anchorTop
      return Math.max(min, value)
      }
      wx.createSelectorQuery()
      .select('.anchor-screen-bottom')
      .boundingClientRect()
      .selectViewport()
      .scrollOffset()
      .exec(res => {
        this.data.anchor.anchorScreenBottom = res[0].bottom
      })
      wx.createSelectorQuery()
      .selectAll('.anchor-top')
      .boundingClientRect()
      .selectViewport()
      .scrollOffset()
      .exec(res => {
        this.data.anchor.anchorTop = res[0].top
        this.setData({
          'anchor.deviceHeight': getSwiperHeight()
        })
      })
      wx.createSelectorQuery()
      .selectAll('.anchor-bottom')
      .boundingClientRect()
      .selectViewport()
      .scrollOffset()
      .exec(res => {
        this.data.anchor.anchorBottom = res[0].bottom
        this.setData({
          'anchor.deviceHeight': getSwiperHeight()
        })
      })
    },
})

適配多頁面

當(dāng)然,肯定要適配每個頁面的高度不一樣的情況甸鸟。方案也很簡單惦费,屏幕底部的錨只需要一個了,給每個 swiper-item 的都添加兩個錨點抢韭,和之前一樣一個在上面一個在下面薪贫,在切換頁面的時候,根據(jù)當(dāng)前頁面的錨點重新計算一下高度篮绰,然后設(shè)置進(jìn)去后雷。

只需要在原有基礎(chǔ)上改一下代碼:

page.wxml

<view>
    <swiper style="height: {{anchor.deviceHeight + 'px'}}" bindchange="swiperChange">
        <swiper-item>
            <view class="anchor-top"></view>
            <!-- 你的內(nèi)容 -->
            <view class="anchor-bottom"></view>
        </swiper-item>
        <swiper-item>
            <view class="anchor-top"></view>
            <!-- 你的內(nèi)容 -->
            <view class="anchor-bottom"></view>
        </swiper-item>
    </swiper>
    <view class="anchor-screen-bottom"></view>
</view>

page.wxss

CSS 不需要改動

page.js

Page({
    data: {
        anchor: {
            deviceHeight: 0,
      anchorTop: 0,
      anchorBottom: 0,
      anchorScreenBottom: 0
        }
    },
    onReady: function() {
        this.computeSwiperHeight(0)
    },
    swiperChange(e) {
    this.computeSwiperHeight(e.detail.current)
  },
    computeSwiperHeight(pageIndex) {
      let getSwiperHeight = () => {
      let min = this.data.anchor.anchorScreenBottom - this.data.anchor.anchorTop;
      let value = this.data.anchor.anchorBottom - this.data.anchor.anchorTop
      return Math.max(min, value)
      }
      wx.createSelectorQuery()
      .select('.anchor-screen-bottom')
      .boundingClientRect()
      .selectViewport()
      .scrollOffset()
      .exec(res => {
        this.data.anchor.anchorScreenBottom = res[0].bottom
      })
      wx.createSelectorQuery()
      .selectAll('.anchor-top')
      .boundingClientRect()
      .selectViewport()
      .scrollOffset()
      .exec(res => {
        this.data.anchor.anchorTop = res[0][pageIndex].top
        this.setData({
          'anchor.deviceHeight': getSwiperHeight()
        })
      })
      wx.createSelectorQuery()
      .selectAll('.anchor-bottom')
      .boundingClientRect()
      .selectViewport()
      .scrollOffset()
      .exec(res => {
        this.data.anchor.anchorBottom = res[0][pageIndex].bottom
        this.setData({
          'anchor.deviceHeight': getSwiperHeight()
        })
      })
    },
})

實現(xiàn)效果

  1. swiper 的高度高度根據(jù)內(nèi)容自適應(yīng)
  2. swiper 的高度最小占滿屏幕季惯,最大和內(nèi)容一樣高(為了用戶滑動體驗(如果劃頁后高度突然變小吠各,用戶在原來的位置就劃不回去了)
  3. 適配不同高度的頁面

這個方案是了實現(xiàn)為自己的需求而寫的臀突,應(yīng)該不適應(yīng)全部的場景,不過希望可以為你提供一點思路贾漏。

感想

小程序里的坑真的很多候学,而且有些 API 設(shè)計的很奇怪,真的不知道當(dāng)初開發(fā)人員懷著怎樣的心路歷程設(shè)計出的 API纵散。

個人感覺小程序就是給前端新造了一個輪子梳码,更新還很不及時,有很多陳年老 Bug伍掀,比如本文講的 swiper掰茶。

前端娛樂圈發(fā)展這么快,感覺小程序可能會跟不上潮流蜜笤。

最后

給我正在開發(fā)的小程序預(yù)熱一下~

image

歡迎關(guān)注~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末濒蒋,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子把兔,更是在濱河造成了極大的恐慌沪伙,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件县好,死亡現(xiàn)場離奇詭異围橡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)缕贡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來善绎,“玉大人黔漂,你說我怎么就攤上這事≠鹘矗” “怎么了炬守?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剂跟。 經(jīng)常有香客問我减途,道長,這世上最難降的妖魔是什么曹洽? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任鳍置,我火速辦了婚禮,結(jié)果婚禮上送淆,老公的妹妹穿的比我還像新娘税产。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布辟拷。 她就那樣靜靜地躺著撞羽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衫冻。 梳的紋絲不亂的頭發(fā)上诀紊,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音隅俘,去河邊找鬼邻奠。 笑死,一個胖子當(dāng)著我的面吹牛为居,可吹牛的內(nèi)容都是我干的碌宴。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼蒙畴,長吁一口氣:“原來是場噩夢啊……” “哼唧喉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起忍抽,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤八孝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鸠项,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體干跛,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年祟绊,在試婚紗的時候發(fā)現(xiàn)自己被綠了楼入。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡牧抽,死狀恐怖嘉熊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扬舒,我是刑警寧澤阐肤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站讲坎,受9級特大地震影響孕惜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晨炕,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一衫画、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓮栗,春花似錦削罩、人聲如沸瞄勾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丰榴。三九已至,卻和暖如春秆撮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背换况。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工职辨, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人戈二。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓舒裤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親觉吭。 傳聞我的和親對象是個殘疾皇子腾供,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 每天的學(xué)習(xí)記錄,可能有的地方寫的不對鲜滩,因為剛學(xué)伴鳖,以后發(fā)現(xiàn)錯的話會回來改掉整體流程 https://develope...
    有點健忘閱讀 4,637評論 0 7
  • 前段時間,多年沒有聯(lián)系的朋友聽說我在解讀精靈卡徙硅,約了晚上的精靈卡榜聂。 她還是那樣美麗依舊。 她咨...
    郗紅嘉閱讀 175評論 0 7
  • 今天是我日更第十七天了嗓蘑。昨天試著投稿一篇文章须肆,被兩個專題加入,今天投了三篇文章桩皿,其中一篇被三個專題加入豌汇,一篇被兩個...
    風(fēng)柔水靜閱讀 559評論 7 13
  • 由趙寶剛導(dǎo)演執(zhí)導(dǎo)的熱播電視劇《青春斗》迎來了完結(jié)佛嬉,說實話一開始看到演員表的時候我著實擔(dān)心鄭爽會像以往一樣柜思,只是瞇眼...
    暢鎖欲言閱讀 402評論 3 1
  • 1.我萬分幸運并感激,一大早媽媽就做地米菜煮雞蛋給到全家人巷燥。 2.我萬分幸運并感激赡盘,今天農(nóng)歷三月初三,中午到工作室...
    羅文均閱讀 119評論 0 2