android scrollview 懒加载图片,小程序之图片懒加载[完美方案,你不来看看?]

效果图

既然来了,把妹子都给你。

AAffA0nNPuCLAAAAAElFTkSuQmCC

image

定义

懒加载,前端人都知道的一种性能优化方式,简单的来说,只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。

实现原理

监听页面的scroll事件,判读元素距离页面的top值是否是小于等于页面的可视高度

判断逻辑代码如下

element.getBoundingClientRect().top <= document.documentElement.clientHeight ? 显示 : 默认

我们知道小程序页面的脚本逻辑是在JsCore中运行,JsCore是一个没有窗口对象的环境,所以不能在脚本中使用window,也无法在脚本中操作组件。

所以关于图片懒加载就需要在数据上面做文章了。

页面

页面上面只需要根据数据的某一个字段来判断是否显示图片就可以了,字段为Boolean类型,当为false的时候显示默认图片就行了。

代码大概长成这样

wx:key="{{index}}">

布局跟简单,view组件里面有个图片,并循环list,有多少就展示多少

image组件的src字段通过每一项的show来进行绑定,active是加了个透明的过渡

样式image{    transition: all .3s ease;    opacity: 0;

}.active{    opacity: 1;

}

逻辑

本位主要讲解懒加载,所以把数据写死在页面上了

数据结构如下:

AAffA0nNPuCLAAAAAElFTkSuQmCC

image

我们使用两种方式来实现懒加载,准备好没有,一起来快乐的撸码吧。

WXML节点信息

小程序支持调用createSelectQuery创建一个SelectorQuery实例,并使用select方法来选择节点,并通过boundingClientRect来获取节点信息。wx.createSelectorQuery().select('.item').boundingClientRect((ret)=>{    console.log(ret)

}).exec()

显示结果如下

AAffA0nNPuCLAAAAAElFTkSuQmCC

image

悄悄告诉你,小程序里面有个onPageScroll函数,是用来监听页面的滚动的。

还有个getSystemInfo函数,可以获取获取系统信息,里面包含屏幕的高度。

接下来,思路就透彻了吧。还是上面的逻辑, 扒拉扒拉直接写代码就行了,这里只写下主要的逻辑,完整代码请戳文末githubshowImg(){    let group = this.data.group    let height = this.data.height  // 页面的可视高度

wx.createSelectorQuery().selectAll('.item').boundingClientRect((ret) => {

ret.forEach((item, index) => {       if (item.top <= height) { 判断是否在显示范围内

group[index].show = true // 根据下标改变状态

}

})     this.setData({

group

})

}).exec()

}

onPageScroll(){ // 滚动事件

this.showImg()

}

至此,我们完成了一个小程序版的图片懒加载,只是思维转变了下,其实并没有改变实现方式。我们来学些新的东西吧。

节点布局相交状态

节点相交状态是啥?它是一个新的API,叫做IntersectionObserver, 本文只讲解简单的使用,了解更多请猛戳没错,就是点我

小程序里面给它的定义是节点布局交叉状态API可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。

里面设计的概念主要有五个,分别为参照节点:以某参照节点的布局区域作为参照区域,参照节点可以有多个,多个话参照区域取它们的布局区域的交集

目标节点:监听的目标,只能是一个节点

相交区域:目标节点与参照节点的相交区域

相交比例:目标节点与参照节点的相交比例

阈值:可以有多个,默认为[0], 可以理解为交叉比例,例如[0.2, 0.5]

关于它的API有五个,依次如下

1、createIntersectionObserver([this], [options]),见名知意,创建一个IntersectionObserver实例

2、intersectionObserver.relativeTo(selector, [margins]), 指定节点作为参照区域,margins参数可以放大缩小参照区域,可以包含top、left、bottom、right四项

3、intersectionObserver.relativeToViewport([margin]),指定页面显示区域为参照区域

4、intersectionObserver.observer(targetSelector, callback),参数为指定监听的节点和一个回调函数,目标元素的相交状态发生变化时就会触发此函数,callback函数包含一个result,下面再讲

5、intersectionObserver.disconnect() 停止监听,回调函数不会再触发

然后说下callback函数中的result,它包含的字段为字段名类型说明intersectionRatioNumber相交比例

intersectionRectObject相交区域的边界,包含 left 、 right 、 top 、 bottom 四项

boundingClientRectObject目标节点布局区域的边界,包含 left 、 right 、 top 、 bottom 四项

relativeRectObject参照区域的边界,包含 left 、 right 、 top 、 bottom 四项

timeNumber相交检测时的时间戳

我们主要使用intersectionRatio进行判断,当它大于0时说明是相交的也就是可见的。

先来波测试题,请说出下面的函数做了什么,并且log函数会执行几次1、

wx.createIntersectionObserver().relativeToViewport().observer('.box', (result) => {    console.log('监听box组件触发的函数')

})

2、

wx.createIntersectionObserver().relativeTo('.box').observer('.item', (result) => {    console.log('监听item组件触发的函数')

})3、

wx.createIntersectionObserver().relativeToViewport().observer('.box', (result) => {    if(result.intersectionRatio > 0){        console.log('.box组件是可见的')

}

})

duang,揭晓答案。

第一个以当前页面的视窗监听了.box组件,log会触发两次,一次是进入页面一次是离开页面

第二个以.box节点的布局区域监听了.item组件,log会触发两次,一次是进入页面一次是离开页面

第三个以当前页面的视窗监听了.box组件,log只会在节点可见的时候触发

好了,题也做了,API你也掌握了,相信你已经可以使用IntersectionObserver来实现图片懒加载了吧,主要逻辑如下let group = this.data.group // 获取图片数组数据for (let i in this.data.group){   wx.createIntersectionObserver().relativeToViewport().observe('.item-'+ i, (ret) => {       if (ret.intersectionRatio > 0){

group[i].show = true

}       this.setData({

group

})

})

}

最后

至此,我们使用两种方式实现了小程序版本的图片懒加载,可以发现,使用IntersectionObserver来实现不要太酸爽。

本文代码请戳github

作者:an祭

链接:https://www.jianshu.com/p/5164a7bda33d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现这个效果可以采用两种方案: 1. 使用 CoordinatorLayout 实现 CoordinatorLayout 是一个非常强大的布局容器,它可以协调多个子 View 的交互行为。在这个场景下,我们可以将标题栏作为 CoordinatorLayout 的直接子 View,将 ScrollView 作为标题栏的兄弟 View,然后使用 app:layout_behavior 属性指定标题栏的行为为 AppBarLayout.ScrollingViewBehavior,这样当 ScrollView 滑动时,标题栏就会自动滑动。 示例代码如下: ```xml <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="My Title" /> </com.google.android.material.appbar.AppBarLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!-- Your content here --> </ScrollView> </androidx.coordinatorlayout.widget.CoordinatorLayout> ``` 需要注意的是,这种方案需要使用 AndroidX 库中的 CoordinatorLayout 和 Material Design 组件库中的 AppBarLayout 和 MaterialToolbar。 2. 使用自定义 Behavior 实现 如果你不想使用 CoordinatorLayout,或者你需要实现一些比较特殊的效果,那么可以考虑使用自定义 Behavior 实现。具体来说,我们可以定义一个 Behavior,继承自 AppBarLayout.ScrollingViewBehavior,并重写 onNestedPreScroll 方法,在 ScrollView 滑动之前处理标题栏的滑动。 示例代码如下: ```java public class MyBehavior extends AppBarLayout.ScrollingViewBehavior { public MyBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { // 计算标题栏需要滑动的距离 int distance = Math.min(child.getHeight(), dy); // 滑动标题栏 child.setTranslationY(-distance); // 更新 consumed 数组,表示已经消耗了滑动距离 consumed[1] = distance; return true; } } ``` 然后在布局文件中将标题栏的 Behavior 设置为我们定义的 MyBehavior: ```xml <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_behavior=".MyBehavior"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="My Title" /> </com.google.android.material.appbar.AppBarLayout> ``` 需要注意的是,这种方案需要手动处理标题栏的滑动,因此需要在 onNestedPreScroll 方法中计算标题栏需要滑动的距离,并使用 setTranslationY 方法滑动标题栏。同时,需要更新 consumed 数组,表示已经消耗了滑动距离,这样才能确保滑动事件正确地传递给 ScrollView

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值