全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

xmlplus组件设计系列之下拉刷新(PullRefresh)(6)

“下拉刷新”由著名设计师 Loren Brichter 设计,并应用于 Twitter 第三方应用 Tweetie 中。2010年4月,Twitter 收购 Tweetie 开发商 Atebits 后,该专利归 Twitter 所有。这一章我们就来看看如何实现一个简单的下拉刷新组件。

目标组件分析

和前面在设计组件时的做法一样,我们先想想看最终的成品组件是如何使用的,这需要点想像力。下拉刷新组件看成一个容器组件是合理的,用户可以对容器的内容进行下拉操作。如果用户完成了完整的下拉触发操作,该组件应该会有下拉完成的事件反馈,假定这个事件名为 ready。根据以上的分析,我们很有可能得到下面的一个该组件的应用示例。

Example1: {
 xml: `<PullRefresh id='example'>
    <h1>Twitter</h1>
    <h2>Loren Brichter</h2>
   </PullRefresh>`,
 fun: function (sys, items, opts) {
  sys.example.on("ready", () => console.log("ready"));
 }
}

示例中的使用方式是非常简洁的,但我们还漏了一点。如果你用过一些新闻客户端,在某些情况下,此客户端会自动触发下拉刷新操作。比如,刚进入客户端页面或者由于软件推送机制产生的被动列表更新,这都将导致客户端下拉刷新操作的触发。所以如上的 PullRefresh 组件还应该提供一个触发自动刷新的操作接口。好了,下面是加入下拉刷新接口的应用示例。

Example2: {
 xml: `<PullRefresh id='example'>
    <h1>Twitter</h1>
    <h2>Loren Brichter</h2>
    <button id='refresh'>click</button>
   </PullRefresh>`,
 fun: function (sys, items, opts) {
  sys.example.on("ready", () => console.log("ready"));
  sys.refresh.on("click", items.example.refresh);
 }
}

基本框架

现在让我们把目光转移到下拉刷新组件的内部,看看该如何去实现。观察文章开始部分的大图,很自然地我们可以将整个组件划分为三个子组件,如下面的 XML 文档所示。

<div id="refresh">
 <Status id="status"/>
 <div id="content"></div>
</div>

外围 div 元素包含两个子组件:其中一个是状态指示条,用于显示“下拉刷新”、“松开刷新”、“加载中...”以及“刷新成功”四个状态提示,这里暂时使用未定义的 Status 组件替代;另一个 div 元素用于容纳下拉刷新组件的包含内容。到现在,大概可以想得出该组件的工作逻辑了,于是我们可以给出下面的一个基本的组件框架。

PullRefresh: {
 css: "#refresh { position: relative; height: 100%;...}",
 xml: `<div id="refresh">
   <Status id="status"/>
   <div id="content"/>
   </div>`,
 map: { appendTo: "content" },
 fun: function (sys, items, opts) {
  sys.content.on("touchstart", e => {
   // 侦听 touchmove 和 touchend事件
  });
  function touchmove(e) {
   // 1 处理状态条与内容内面跟随触点移动
   // 2 根据触点移动的距离显示相当的状态条内容
  }
  function touchend(e) {
   // 1 移除 touchmove 和 touchend 事件
   // 2 根据触点移动的距离决定返回原始状态或者进入刷新状态并派发事件
  }
 }
}

状态条的实现

如前面提到的,状态条组件包含四个状态提示,并且每一时刻仅显示一个状态。对于状态的切换,这里会先用到我们下一章将讲到的路由组件 ViewStack,这里仅需要了解如何使用即可。组件 ViewStack 对外只显示子级的一个子组件,同时侦听一个 switch 事件,该事件的派发者携带了一个切换到的目标对象的名称,也就是 ID。该组件根据这个 ID 来切换到目标视图。下面是状态条组件的完整实现。

Status: {
 css: "#statusbar { height: 2.5em; line-height: 2.5em; text-align: center; }",
 xml: <ViewStack id="statusbar">
   <span id="pull">下拉刷新</span>
   <span id="ready">松开刷新</span>
   <span id="loading">加载中...</span>
   <span id="success">刷新成功</span>
   </ViewStack>,
 fun: function (sys, items, opts) {
  var stat = "pull";
  function getValue() {
   return stat;
  }
  function setValue(value) {
   sys.statusbar.trigger("switch", stat = value);
  }
  return Object.defineProperty({}, "value", { get: getValue, set: setValue });
 }
}

该组件提供一个 value 接口用户设置与获取组件的显示状态。父级组件可根据不同的时机调用该接口。

最终实现

有了上面的储备,让我们来填充完下拉刷新组件的细节。下拉刷新过程中会涉及到动画,对于动画目前一般有两种选择,可以使用 JQuery 动画函数,也可以是 css3,这需要看各人喜好了。这里我们选择使用 css3 来实现。为清晰起见,下面的实现仅给出函数部分,其余部分同上。

PullRefresh: {
 fun: function (sys, items, opts) {
  var startY, height = sys.status.height();
  sys.content.on("stouchstart", e => {
   if (items.status.value == "pull") {
    startY = e.y;
    sys.content.on("touchmove", touchmove).on("touchend", touchend);
    sys.content.css("transition", "").prev().css("transition", "");
   }
  });
  function touchmove(e) {
   var offset = e.y - startY;
   if ( offset > 0 ) {
    sys.content.css("top", offset + "px"); 
    sys.status.css("top", (offset - height) + "px");
    items.status(offset > height ? "ready" : "pull");
   }
  }
  function touchend (e) {
   var offset = e.y - startY;
   sys.content.off("touchmove").off("touchend");
   sys.content.css("transition", "all 0.3s ease-in 0s").prev().css("transition", "all 0.3s ease-in 0s");
   if ( offset < height ) {
    sys.content.css("top", "0").prev().css("top", -height + "px");
   } else {
    items.status.value = "release";
    sys.refresh.once("complete", complete);
    sys.content.css("top", height + "px").prev().css("top", "0").trigger("ready");
   }
  }
  function complete() {
   items.status.value = "message";
   setTimeout(() => {
    sys.content.css("top", "0").prev().css("top", -height + "px");
    sys.content.once("webkitTransitionEnd", e => items.status.value = "pull");
   }, 300);
  }
 }
}

对于稍微有点复杂的组件,需要注意组件的组织归类,尽量把具有相近功能的组件放在一起。为了便于叙述,上述所列出的组件示意总把它们视作是同一目录,这一点读者应该能看出来。

本系列文章基于 xmlplus 框架。如果你对 xmlplus 没有多少了解,可以访问 www.xmlplus.cn。这里有详尽的入门文档可供参考。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# xmlplus  # 下拉刷新  # xmlplus组件设计系列之网格(DataGrid)(10)  # xmlplus组件设计系列之文本框(TextBox)(3)  # xmlplus组件设计系列之选项卡(Tabbar)(5)  # xmlplus组件设计系列之路由(ViewStack)(7)  # xmlplus组件设计系列之分隔框(DividedBox)(8)  # xmlplus组件设计系列之树(Tree)(9)  # xmlplus组件设计系列之按钮(2)  # xmlplus组件设计系列之列表(4)  # xmlplus组件设计系列之图标(ICON)(1)  # 客户端  # 让我们  # 我们可以  # 提供一个  # 如何使用  # 切换到  # 如果你  # 文档  # 会有  # 加载中  # 好了  # 你对  # 只显示  # 可以使用  # 可供  # 用过  # 该如何  # 能看  # 所示  # 其中一个 


相关文章: 电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?  再谈Python中的字符串与字符编码(推荐)  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  美食网站链接制作教程视频,哪个教做美食的网站比较专业点?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  如何快速生成专业多端适配建站电话?  建站org新手必看:2024最新搭建流程与模板选择技巧  如何在阿里云高效完成企业建站全流程?  实现点击下箭头变上箭头来回切换的两种方法【推荐】  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  如何挑选优质建站一级代理提升网站排名?  建站主机默认首页配置指南:核心功能与访问路径优化  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  学校为何禁止电信移动建设网站?  建站上市公司网站建设方案与SEO优化服务定制指南  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  如何在Windows 2008云服务器安全搭建网站?  如何在万网主机上快速搭建网站?  建站之星ASP如何实现CMS高效搭建与安全管理?  网站制作专业公司有哪些,如何制作一个企业网站,建设网站的基本步骤有哪些?  建站之星体验版:智能建站系统+响应式设计,多端适配快速建站  宝塔建站助手安装配置与建站模板使用全流程解析  简单实现Android验证码  如何在阿里云域名上完成建站全流程?  小捣蛋自助建站系统:数据分析与安全设置双核驱动网站优化  建站主机是否等同于虚拟主机?  官网网站制作腾讯审核要多久,联想路由器newifi官网  重庆市网站制作公司,重庆招聘网站哪个好?  如何通过FTP空间快速搭建安全高效网站?  微网站制作教程,我微信里的网站怎么才能复制到浏览器里?  非常酷的网站设计制作软件,酷培ai教育官方网站?  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  ,石家庄四十八中学官网?  音乐网站服务器如何优化API响应速度?  中山网站制作网页,中山新生登记系统登记流程?  如何用搬瓦工VPS快速搭建个人网站?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  建站之星后台搭建步骤解析:模板选择与产品管理实操指南  开源网站制作软件,开源网站什么意思?  如何快速配置高效服务器建站软件?  黑客如何利用漏洞与弱口令入侵网站服务器?  高端网站建设与定制开发一站式解决方案 中企动力  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  建站之星安装模板失败:服务器环境不兼容?  C++用Dijkstra(迪杰斯特拉)算法求最短路径  制作门户网站的参考文献在哪,小说网站怎么建立? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。