前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >移动端效果之ScrollList

移动端效果之ScrollList

作者头像
糊糊糊糊糊了
发布于 2018-05-09 08:00:52
发布于 2018-05-09 08:00:52
1.2K00
代码可运行
举报
文章被收录于专栏:糊一笑糊一笑
运行总次数:0
代码可运行

写在前面

列表一直是展示数据的一个重要方式,在手机端的列表展示又和PC端展示不同,毕竟手机端主要靠滑。之前手机端之前一直使用的IScroll,但是IScroll本身其实有很多兼容性BUG,想改动一下需求也很不容易,可以看我之前写的这一文章IScroll那些事——内容不足时下拉刷新(这里并不是说IScroll不好,里面对手机、浏览器兼容性都做了大量的处理,只是当遇到bug时或者想改一下需求时不时特别方便,毕竟是一个这么大的库)。因此也一直想了解一下这类列表的实现原理,万一真到时候可以自己写一个,这样自己维护自己的代码也可以更加得心应手。

下面主要是阅读了饿了么UI组件库mint-ui然后编写出来的效果图:

代码请看这里:github

移动端效果之swiper

移动端效果之picker

移动端效果之cellSwiper

移动端效果之IndexList

1 核心解析

1.1 整体思路图

1.2 HTML结构

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<div class="page-loadmore-wrapper">
    <div id='loadMore' class="loadmore">
        <div id="loadMoreContent" class="loadmore-content">
            <!-- 这里是顶部状态生成的地方 -->
            <ul class="page-loadmore-list" id="loadMoreList"></ul>
            <!-- 这里是底部状态生成的地方 -->
        </div>
    </div>
</div>

这里有一点需要注意,滑动内容部分需要一个设置为overflow:scroll容器,如果不设置,就会一直向上找,直到最后返回window,这点在下面的代码可以体现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 获取滚动容器
 * @param  DOM element 
 * @return 
 */
getScrollEventTarget: function(element) {
    var currentNode = element;
    while (currentNode && currentNode.tagName !== 'HTML' &&
         currentNode.tagName !== 'BODY' && currentNode.nodeType === 1) {
        var overflowY = document.defaultView.getComputedStyle(currentNode).overflowY;
        if (overflowY === 'scroll' || overflowY === 'auto') {
            return currentNode;
        }
        currentNode = currentNode.parentNode;
    }
    return window;
}

1.3 滑动弹性与状态变化

这两点我们在touchmove事件中可以找到相应的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 弹性滑动
// 这里用手指滑动的位移除以比例系数来得出内容应该滑动的位移
// 因此这里的内容滑动的位移一定是会小于手指滑动的位移的,除非你将系列设置为小于1,那我就没得话说了
// 于是就造成了一种滑动又滑不动的感觉
var distance = (_this.currentY - _this.startY) / _this.config.distanceIndex;

// 下移条件
// 1. 必须有刷新函数
// 2. 方向为向下
// 3. 初始的scrollTop为0
// 4. 状态不为加载中
if (typeof _this.config.topMethod === 'function' && _this.direction === 'down' &&
    _this.getScrollTop(_this.scrollEventTarget) === 0 && _this.topStatus !== 'loading') {
    event.preventDefault();
    event.stopPropagation();

    if (_this.config.maxDistance > 0) {
        _this.translate = distance <= _this.config.maxDistance ? distance - _this.startScrollTop : _this.translate;
    } else {
        _this.translate = distance - _this.startScrollTop;
    }

    if (_this.translate < 0) {
        _this.translate = 0;
    }

    // 这里是滑动中(touchmove)时应该判断的
    // 如果滑动的位移操作了我们设置的值就置为pull
    // 同时更新状态,改变内容的transform
    // 同理可以在向上拉动的时候找到相应的代码,这里不作累述
    _this.topStatus = _this.translate >= _this.config.topDistance ? 'drop' : 'pull';

    Event.trigger('topStatus', _this.topStatus);
    Event.trigger('translate', _this.translate);
}

// 在向上滑动的过程中,还需要时刻检测是否已经滑倒最下面了
// 如果没有滑倒最下面,则正常滑动,否则,加载新的数据
if (_this.direction === 'up') {
    _this.bottomReached = _this.bottomReached || _this.checkBottomReached();
}
1.4 加载数据

当状态在loading的时候,就是加载数据的时候,而只有当滑动停止之后,状态才需要置为loading,因此加载数据的代码需要在touchend中执行,具体看下面代码注释:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 这里分析向下刷新数据时候的代码
// 向上部分的类似,可以自行去了解
if (_this.direction === 'down' && _this.getScrollTop(_this.scrollEventTarget) === 0 && _this.translate > 0) {
    // 这里触发topDropped为true是为了给内容部分加上动画
    Event.trigger('topDropped', true);

    // 判断当前是否已经拉倒了足够的位移,只有状态为drop的时候放手才会加载数据
    if (_this.topStatus === 'drop') {
        // 重置状态为loading,改变位移
        Event.trigger('topStatus', 'loading');
        // 向下移动50px像素是为了展示出loading的文字
        Event.trigger('translate', 50);

        // 加载数据
        _this.config.topMethod(function() {
            var args = [].slice.call(arguments);
            _this.onTopLoaded.apply(_this, args);
        });
    } else {
        // 如果向下拉动状态仍为pull,说明拉动的距离很小
        Event.trigger('translate', 0);
        Event.trigger('topStatus', 'pull');
    }
}
1.5 上拉加载数据完成之后

这里与下拉刷新有一点小小的不同,这里贴一下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
onBottomLoaded: function(list, isAllLoaded) {
    Event.trigger('bottomStatus', 'pull');
    Event.trigger('bottomDropped', false);
    Event.trigger('data', list);

    // 这里给scrollEventTarget设置了scrollTop为50是为了防止跳动
    if (this.scrollEventTarget === window) {
        document.body.scrollTop += 50;
    } else {
        this.scrollEventTarget.scrollTop += 50;
    }

    Event.trigger('translate', 0);
    this.bottomAllLoaded = isAllLoaded;
}

1.6 关于数据初始化填充

在数据内容不足一屏时,如果设置了autoFill字段为true的话,会自动调用一遍bottomMethod来填充数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
fillContainer: function() {
    var _this = this;

    // 如果自动填充
    if (this.config.autoFill) {
        // 根据滚动容器来判断当前数据是否已经填充满容器
        if (this.scrollEventTarget === window) {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
                document.documentElement.getBoundingClientRect().bottom;
        } else {
            this.containerFilled = this.$el.getBoundingClientRect().bottom >=
            this.scrollEventTarget.getBoundingClientRect().bottom;
        }

        // 如果数据没有填充满容器,则加载数据
        if (!this.containerFilled) {
            // 这里算是一点小遗憾,为了在自动加载loading的时候,显示出状态
            // 将内容部分位移了-50px,这就是为什么在自动加载的时候会出现一个跳动的过程
            Event.trigger('bottomStatus', 'loading');
            Event.trigger('translate', -50);
            var data = this.config.bottomMethod(function(list) {
                Event.trigger('data', list);
                Event.trigger('bottomStatus', 'pull');
                Event.trigger('translate', 0);
            });
        }
    }
},

2 总结

最开始会认为这样的效果实现起来会比较复杂(不过实际上确实也写了快500到600行代码了?),但是真正分析起来,其实觉得代码还好,并没有想像得辣么困难。遇上自己想要实现的东西,就努力地去啃吧,就像遇到了你喜欢的女孩一样?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
App跨平台技术2025年深度解析:核心原理与最佳实践
2025年标志着跨平台移动开发技术的重要转折点。经过多年发展,各大框架已从实验性质转向生产级成熟度,全球跨平台开发者已超过300万,成为企业数字化转型的关键技术支撑。
蓝葛亮
2025/06/15
2290
App跨平台技术2025年深度解析:核心原理与最佳实践
KMM跨平台开发入门,看这一篇就够了~
近些年,不管是最初的RN还是到现在的Flutter、Compose,他们都在做着一件事——跨平台。
黄林晴
2022/10/24
4.9K0
KMM跨平台开发入门,看这一篇就够了~
Hello World —— 使用 Kotlin 开发跨平台应用
在移动开发领域,Android 和 iOS 版本的应用程序通常会有很多共同点,背后的业务逻辑基本也是一致的。文件下载,读写数据库,从远程服务器获取数据,解析远程数据等等。所以我们为什么不只写一次业务逻辑代码,在不同的平台上共享呢?
路遥TM
2021/08/31
2.4K0
谷歌社区说|聊聊Compose跨平台与KMM
大家好我是黄林晴,也是图书《Android Jetpack开发:原理解析与应用实战》的作者。上一次在社区分享还是在三年前的Android 11见面会上,本次为大家分享的主题是Compose Multiplatform和KMM。这里是本次分享的文字版。
黄林晴
2023/12/28
1.9K0
谷歌社区说|聊聊Compose跨平台与KMM
Compose也能开发iOS了,快来体验~
在之前,我们已经体验了Compose for Desktop 与 Compose for Web,目前Compose for iOS 已经有尚未开放的实验性API,乐观估计今年年底将会发布Compose for iOS。同时Kotlin也表示将在2023年发布KMM的稳定版本。
黄林晴
2023/05/31
1.5K0
Compose也能开发iOS了,快来体验~
Kotlin/Native KMM项目架构
Kotlin Multiplatform Mobile ( KMM ) 是一个 SDK,旨在简化跨平台移动应用程序的创建。在 KMM 的帮助下,您可以在 iOS 和 Android 应用程序之间共享通用代码,并仅在必要时编写特定于平台的代码。
libill
2021/10/17
3.4K0
Kotlin/Native KMM项目架构
Android经典实战之Kotlin Multiplatform 中,如何处理不同平台的 API 调用
在 Kotlin Multiplatform 项目中,expect 和 actual 关键字被用于处理不同平台的 API 调用。以下是如何使用这些关键字的详细步骤和规则:
AntDream
2024/08/19
3630
Android经典实战之Kotlin Multiplatform 中,如何处理不同平台的 API 调用
Android经典实战之Kotlin Multiplatform跨平台开发
Kotlin Multiplatform(KMP)是JetBrains开发的一项开源技术,它允许开发者在多个平台上创建应用程序,同时高效地重用代码,保留原生编程的优势 。KMP支持在iOS、Android、macOS、Windows、Linux等多种操作系统上运行应用程序 。
AntDream
2024/08/19
7410
Android经典实战之Kotlin Multiplatform跨平台开发
再探Kotlin 跨平台——迁移Paging分页库至KMM
KMM的发展除了靠官方社区的支持外,一些大企业的开源落地也尤为重要。从这些开源中我们需要借鉴他的设计思想和实现方式。从而在落地遇到问题时,寻得更多的解决办法。
黄林晴
2022/11/21
1.3K0
再探Kotlin 跨平台——迁移Paging分页库至KMM
Android实战经验分享之用Kotlin中的Jetpack Compose构建声明式UI
Kotlin中的Jetpack Compose是用于构建Android用户界面的声明式UI工具包。它通过Kotlin语言来编写界面,旨在简化和加速UI开发过程。Jetpack Compose由谷歌推出,作为传统的视图系统(如XML布局和Android View组件)的替代或补充。下面我们来看看关于Jetpack Compose的核心概念、主题和样式、导航和预览功能:
AntDream
2024/08/12
7240
Android实战经验分享之用Kotlin中的Jetpack Compose构建声明式UI
跨平台开发框架 Compose Multiplatform 1.0 发布
JetBrains 工程师 Sebastian Aigner 在官方博客宣布,Compose Multiplatform(Kotlin 的声明式 UI 框架)已经发布了 1.0 版本,现在可以在生产环境中使用了。此版本主要解决质量和稳定性问题,同时修复关键问题和错误。
深度学习与Python
2021/12/09
1K0
开源公告|Kuikly 跨平台开发框架
Kuikly 是腾讯大前端领域 Oteam(公司级)推出的,面向客户端开发的全新跨端解决方案。Kuikly 基于 Kotlin Multiplatform(KMP) 技术,可以使用 Kotlin 原生开发语言创建 Android、iOS、鸿蒙、Web、小程序应用。
腾讯开源
2025/04/30
1.8K0
开源公告|Kuikly 跨平台开发框架
别具特色的跨平台移动开发 - Kotlin Multiplatform Mobile
而在跨平台移动的技术选择上来说,最流行两个就是React Native与Flutter了。
御剑
2022/06/07
1.8K0
别具特色的跨平台移动开发 - Kotlin Multiplatform Mobile
Compose 跨平台现状
Compose 能应用于跨平台,主要是基于 KMM 架构,KMM 的介绍可以查看官方文档《Get started with Kotlin Multiplatform Mobile[1]》,我们来看下 KMM 的简单架构:
codelang
2022/11/30
3.7K0
Compose 跨平台现状
IDEA 又出新神器,一套代码适应多端!
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/05/18
5540
IDEA 又出新神器,一套代码适应多端!
Kotlin Multiplatform 实战记 | QCon
10 月 21 日我在上海举办的 QCon 全球软件开发大会上分享了 Kotlin Multiplatform 相关的内容,这里记录成文章,分享给你。
深度学习与Python
2021/11/19
1.8K0
JetBrains 发布了 Kotlin Multiplatform 的首个稳定版本
JetBrains 提供了 Kotlin Multiplatform 的首个稳定版本,支持跨 iOS、Android、桌面、Web 和服务器进行代码共享——尽管用于共享用户界面(UI)代码的部分,Compose Multiplatform,仅适用于 Android 和桌面。
深度学习与Python
2023/11/17
3530
JetBrains 发布了 Kotlin Multiplatform 的首个稳定版本
JetBrains 又出了一款新神器,一套代码适应多端!
看到一款基于多端的 UI 调试工具,一套代码适应多端,真的是太棒了,下面分享给大家。
程序员小猿
2021/07/06
5170
JetBrains 又出了一款新神器,一套代码适应多端!
看到一款基于多端的 UI 调试工具,一套代码适应多端,真的是太棒了,下面分享给大家。
好好学java
2021/07/28
4960
JetBrains 又出了一款新神器,一套代码适应多端!
开源 | 从 SQLlin 的更新看 Kotlin Multiplatform 技术更迭
最初,SQLlin 在 Kotlin/Native 平台上基于开源项目 SQLiter(见参考链接 1),目的是避免重复造轮子。虽然 SQLliter 是来自 Touchlab的优秀开源项目,但最近一年维护更新缓慢。在本文撰写时,SQLiter 于 2023 年 11 月发布了 1.3.0 和 1.3.1 两个版本(1.3.1升级到了 Kotlin 1.9.21,用于修复 1.9.20 的 Kotlin/Native 库版本号相关的问题)。但在这之前的版本,即 1.2.1 发布于 2022年 8 月,基于 Kotlin 1.6.20,一年以上没有更新。对于 2023 年的项目来说,1.6.20 过于老旧。老旧的版本导致了如下一些问题。
携程技术
2024/01/23
3470
开源 | 从 SQLlin 的更新看 Kotlin Multiplatform 技术更迭
推荐阅读
相关推荐
App跨平台技术2025年深度解析:核心原理与最佳实践
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档