ios下,微信小程序scrollview组件中的fixed元素抖得和帕金森病人一样
问题现象
这个问题是最近在优化小程序代码时发现的。
在ios环境下,微信小程序的scrollview组件包裹着一个position:fixed的view。
当在scrollview组件上滑动时,这个view会疯狂抖动。
直接上图吧:

下面是简化后的代码:
<view class="main">
<scroll-view scroll-y="{{true}}" bindscroll="handleScroll" style="height:100%;" >
<view>
<view class="weui-navbar navbar-fixed">
我是头部fixed元素
</view>
<view>
这里是一大段test文字,用于占位
</view>
</view>
</scroll-view>
</view>
猜测与验证
原生组件?
这个现象在没有简化代码前,我以为我是哪里用了什么原生组件。
因为原生组件在ios下的定位缓慢,导致了这个问题的出现。
但是当我的代码简化到上面这一步的时候,发现并没有应用原生组件。
ios下橡皮筋功能的影响?
问题在于我去掉了scroll-view后,滚动得不错,这个头部fixed的元素并没有抖动。
确定是scroll-view组件下fixed元素随着滑动就会抖动
到这一步我就确定了问题的原因,所以当然我是要先百度一下答案的。
于是我果然发现了一堆难兄难弟:ios下scroll-view中fixed元素无法固定。
貌似他们遇到的问题比我还严重啊,都像一条咸鱼一样跟着滚了,而我的只是得了帕金森。
简单场景解决方案
上面的问题还没有官方人员回答。
不过最好的解决方案其实就是将fixed元素移出scroll-view,这个没什么好多说的。
元素都fixed了,没道理还要放在scroll-view中是吧?
复杂场景解决方案
既然说了上面是简单场景,那么就肯定有复杂场景嘛。
我元素都fixed了,确实是没道理要放在一个scroll-view元素中包裹着。
但是有的事就是这么没道理啊。
就比如我的微信小程序肯定没有示例这么简单,里面这个fixed元素不能移出去。
因为这个元素的fixed状态并不是固定的,最开始他需要跟随页面一起滚动,当和顶部贴紧后,它就变成fixed了。
废话少说,现在就说一下我的解决方案的思路:
既然要随着页面一起滚动,那么肯定是要保证这个元素在scroll-view中的。
而scroll-view中的fixed元素肯定会抖,所以这个元素又一定要放在scroll-view外。
看似鱼与熊掌不可兼得,实际上我们搞两个人一人取鱼,一人取熊掌就好了嘛。
我们可以在scroll-view外设置一个同样的元素,并将其设置为fixed,并且隐藏。
当scroll-view内部的元素贴紧顶部后,将内部的元素隐藏,再显示外部的元素即可。
以下是实现代码:
index.wxml:
<view class="main">
<view class="navbar navbar-fixed" hidden="{{scrollTop<=initTop}}">
我是头部fixed元素
</view>
<scroll-view scroll-y="{{true}}" bindscroll="handleScroll" style="height:100%;" >
<view>
<view>
这里是一大段test文字,用于占位
</view>
<view id="navbar" class="weui-navbar navbar-fixed" hidden="{{scrollTop>initTop}}">
我是头部fixed元素
</view>
<view>
这里是一大段test文字,用于占位
</view>
</view>
</scroll-view>
</view>
index.js:
Page({
data: {
initTop: 0,
scrollTop: 0,
},
onLoad: function (options) {
let query = wx.createSelectorQuery()
query.select('#navbar').boundingClientRect()
query.exec((res) => {
this.setData({
initTop: res[0].top
})
})
},
handleScroll: function (e) {
this.setData({ scrollTop: e.detail.scrollTop })
}
})
index.wxss:
.navbar-fixed {
position:fixed;
width:100%;
top:0;
left:0;
z-index:100;
}
.navbar{
height:80rpx;
line-height: 80rpx;
background:red;
text-align: center;
color: #fff;
}
隐藏BUG与修复
以上代码如果快速滑动是没有问题,但是当红色头部元素快要贴紧顶部时慢速滑动就会出现一个很诡异的现象:
红色头部元素往下弹动,始终不能贴紧顶部。
而实际上不是红色头部元素往下弹动,而是红色头部元素贴紧顶部后,此时内部头部元素隐藏,那么scrollTop立刻变小。
因为scrollTop变小,小于了initTop,那么内部头部元素再次出现,于是就这样不断循环。
我们这里需要明白hidden实际上是一个display:none的效果,所以这里我们对内部元素的隐藏不能用hidden,而是用visibility:hidden。
这样的话,这个内部元素就只是看不见了而已,并且页面上显示为背景色(这里我们假设是白色),但是还是占用了那么多的空间。
那么scrollTop就不会突然间变小,也就不会造成BUG。
同时,外部的元素会在内部元素变成白色矩形时直接出现,覆盖在内部元素上面,那么内部元素隐藏所造成的白色区域实际上就被外部元素遮挡住了。
当用户在使用时,完全不会感知到内部元素这个白色区域的存在。
好了,这里我们给出修改后的代码:
<view class="main">
<view class="navbar navbar-fixed" hidden="{{scrollTop<=initTop}}">
我是头部fixed元素
</view>
<scroll-view scroll-y="{{true}}" bindscroll="handleScroll" style="height:100%;" >
<view>
<view>
这里是一大段test文字,用于占位
</view>
<view id="navbar" class="weui-navbar navbar-fixed" style="visibility:{{scrollTop>initTop?'hidden':'initial'}}">
我是头部fixed元素
</view>
<view>
这里是一大段test文字,用于占位
</view>
</view>
</scroll-view>
</view>
总结
方法蠢是蠢了点,但是好用啊。
而且万一哪天微信小程序修复了这个问题,咱们的方案不会出问题,替换起来也很简单。
ios下,微信小程序scrollview组件中的fixed元素抖得和帕金森病人一样的更多相关文章
- 微信小程序image组件中aspectFill和widthfix模式应用详解
aspectFill 与 widthfix 都是保持宽高比不变 aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来.也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发 ...
- 微信小程序在组件中获取界面上的节点信息wx.createSelectorQuery
节点信息查询 API 可以用于获取节点属性.样式.在界面上的位置等信息. 最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置. 示例代码: const query = wx.cre ...
- 微信小程序,内容组件中兼容的H5组件
受信任的HTML节点及属性 全局支持class和style属性,不支持id属性. 节点 属性 a abbr address article aside b bdi bdo ...
- 微信小程序-scroll-view组件
<view class="section"> <view class="section__title">vertical scroll& ...
- 微信小程序_(组件)scroll-view可滚动视图
微信小程序scroll-view组件官方文档 传送门 提前准备:使用<view>组件制作五条撑满的横向区域 <!--index.wxml--> Cynical丶Gary < ...
- 微信小程序image组件binderror使用例子(对应html、js中的onerror)
官方文档 binderror HandleEvent 当错误发生时,发布到 AppService 的事件名,事件对象event.detail = {errMsg: 'something wrong' ...
- 微信小程序 scroll-view 填满剩余可用高度
根据微信小程序 scroll-view 文档所述,scroll-view必须给定一个固定高度.那么如果我们想要让它自动填充剩余高度,该怎么办呢? 前言 在说出我的解决方案之前,先来看一下我的页面设计, ...
- 微信小程序倒计时组件开发
今天给大家带来微信小程序倒计时组件具体开发步骤: 先来看下最终效果: git源:http://git.oschina.net/dotton/CountDown 分步骤-性子急的朋友,可以直接看最后那段 ...
- 微信小程序的组件总结
本文介绍微信小程序的组件 视图容器 基础内容 表单组件 导航组件 媒体组件 视图容器 view 布局容器 <view hover-class='bg'>222</view> 可 ...
随机推荐
- 从零开始实现放置游戏(七)——实现挂机战斗(5)RMS系统后台参数校验
前面几章实现了在RMS系统中进行数据的增删查改以及通过Excel批量导入.但仍有遗留的问题,比如在新增或编辑时,怪物的生命值.护甲等数据我们可以输入负值,这种数据是不合理且没有意义的.本章我们就实现服 ...
- Unity Shader 玻璃效果
一个玻璃效果主要分为两个部分,一部分是折射效果的计算,另一部分则是反射.下面分类进行讨论: 折射: 1.利用Grass Pass对当前屏幕的渲染图像进行采样 2.得到法线贴图对折射的影响 3.对采集的 ...
- java线程的简单实用
1.start(): 先来看看Java API中对于该方法的介绍: 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 结果是两个线程并发地运行:当前线程(从调用返回给 start 方法) ...
- Programming In Lua 第六章
1, 2, 3,
- K Balanced Teams CodeForces - 1133E (Dp)
题意: 给出 n 个数,选取其中若干个数分别组成至多 k 组,要求每组内最大值与最小值的差值不超过5,求最后被选上的总人数. 题解: 将a[1∼n] 从小到大排序, f[i][j] 表示到第 i 个数 ...
- python的is与==的区别
is is比较的是两个变量的地址值,如果地址值正确,则返回True,否则返回False,实例如下: 如图所示,a,b列表的数值相等,但地址是不相等的,所以返回True,与值无关 == ==比较的是两个 ...
- Wannafly挑战赛1:Treepath(DFS统计)
题目链接 题意 给出一棵树,问长度为偶数的路径数有多少. 思路 记录路径长度为奇数的数目和为偶数的数目,然后 n * (n-1) / 2 求和即可. #include <bits/stdc++. ...
- ZOJ 3962:Seven Segment Display(思维)
https://vjudge.net/problem/ZOJ-3962 题意:有16种灯,每种灯的花费是灯管数目,代表0~F(十六进制),现在从x开始跳n-1秒,每一秒需要的花费是表示当前的数的花费之 ...
- Codeforces Gym100962J:Jimi Hendrix(树型DP)
http://codeforces.com/gym/100962/attachments 题意:有一个n个节点的字母树,给出n-1条边的信息,代表边上有一个字母,然后给出长度为m的字符串,问是否能在这 ...
- mongodb数据存储
# 打开服务端 直接执行abc.bat文件,如果执行闪退可以把data文件夹里的mongod.lock文件先删除 打开cmd窗口, 输入mongo,启动客户端. 也可以通过NoSQLBooster启动 ...