微信小程序手势冲突?不存在的!

原生的应用经常会有页面嵌套列表,滚动列表能够改变列表大小,然后还能支持列表内下拉刷新等功能。看了很多的小程序好像都没有这个功能,难道这个算是原生独享的吗,难道是由于手势冲突无法实现吗,冷静的思考了一下,又看了看小程序的手势文档(文档地址),感觉我又行了。

实现效果如下:

a.gif

页面区域及支持手势

  • 红色的是列表未展开时内容展示,无手势支持
  • 绿色部分是控制部分,支持上拉下拉手势,对应展开列表及收起列表
  • 蓝色列表部分,支持上拉下拉手势,对应展开列表,上拉下拉刷新等功能
  • 浅蓝色部分是展开列表后的小界面内容展示,无手势支持

原理实现

主要是根据事件系统的事件来自行处理页面应当如何响应,原理其实同原生的差不多。
主要涉及 touchstart、touchmove、touchend、touchcancel 四个

另外的scrollview的手势要借助于 scroll-y、refresher-enable 属性来实现。

之后便是稀疏平常的数学加减法计算题环节。根据不同的内容点击计算页面应当如何绘制显示。具体的还是看代码吧,解释起来又要吧啦吧啦了。

Talk is cheap, show me the code

代码部分

wxml

<!--index.wxml-->
<view>
  <view class="header" style="opacity: {{headerOpacity}};height:{{headerHeight}}px;"></view>
  <view 
    class="toolbar"
    data-type="toolbar"
    style="bottom: {{scrollHeight}}px;height:{{toolbarHeight}}px;"
    catch:touchstart="handleToolbarTouchStart"
    catch:touchmove="handleToolbarTouchMove"
    catch:touchend="handleToolbarTouchEnd"
    catch:touchcancel="handleToolbarTouchEnd"></view>
  <scroll-view 
    class="scrollarea" 
    type="list"
    scroll-y="{{scrollAble}}"
    refresher-enabled="{{scrollAble}}"
    style="height: {{scrollHeight}}px;"
    bind:touchstart="handleToolbarTouchStart"
    bind:touchmove="handleToolbarTouchMove"
    bind:touchend="handleToolbarTouchEnd"
    bind:touchcancel="handleToolbarTouchEnd"
    bindrefresherrefresh="handleRefesh"
    refresher-triggered="{{refreshing}}"
    >
    <view class="item" wx:for="{{[1,2,3,4,5,6,7,8,9,0,1,1,1,1,1,1,1]}}">
      
    </view>
  </scroll-view>

  <view 
    class="mini-header"
    style="height:{{miniHeaderHeight}}px;"
    wx:if="{{showMiniHeader}}">
    
  </view>
</view>

ts

// index.ts
// 获取应用实例
const app = getApp<IAppOption>()

Component({
  data: {
    headerOpacity: 1,
    scrollHeight: 500,
    windowHeight: 1000,
    isLayouting: false,
    showMiniHeader: false,
    scrollAble: false,
    refreshing: false,
    toolbarHeight: 100,
    headerHeight: 400,
    miniHeaderHeight: 200,
    animationInterval: 20,
    scrollviewStartY: 0,
  },
  methods: {
    onLoad() {
      let info = wx.getSystemInfoSync()
      this.data.windowHeight = info.windowHeight
      this.setData({
        scrollHeight: info.windowHeight - this.data.headerHeight - this.data.toolbarHeight
      })
    },
    handleToolbarTouchStart(event) {
      this.data.isLayouting = true
      let type = event.currentTarget.dataset.type
      if (type == 'toolbar') {

      } else {
        this.data.scrollviewStartY = event.touches[0].clientY 
      }
    },
    handleToolbarTouchEnd(event) {
      this.data.isLayouting = false
      
      let top = this.data.windowHeight - this.data.scrollHeight - this.data.miniHeaderHeight - this.data.toolbarHeight
      if (top > (this.data.headerHeight - this.data.miniHeaderHeight) / 2) {
        this.tween(this.data.windowHeight - this.data.scrollHeight, this.data.headerHeight + this.data.toolbarHeight, 200)
      } else {
        this.tween(this.data.windowHeight - this.data.scrollHeight, this.data.miniHeaderHeight + this.data.toolbarHeight, 200)
      }
    },
    handleToolbarTouchMove(event) {
      if (this.data.isLayouting) {
        let type = event.currentTarget.dataset.type
        if (type=='toolbar') {
          this.updateLayout(event.touches[0].clientY + this.data.toolbarHeight / 2)
        } else {
          if (this.data.scrollAble) {
            return
          } else {
            this.updateScrollViewLayout(event.touches[0].clientY)
          }
        }
      }
    },
    handleRefesh() {
      let that = this
      setTimeout(() => {
        that.setData({
          refreshing: false
        })
      }, 3000);
    },
    updateLayout(top: number) {
      if (top < this.data.miniHeaderHeight + this.data.toolbarHeight) {
        top = this.data.miniHeaderHeight + this.data.toolbarHeight
      } else if (top > this.data.headerHeight + this.data.toolbarHeight) {
        top = this.data.headerHeight + this.data.toolbarHeight
      }
      let opacity = (top - (this.data.miniHeaderHeight + this.data.toolbarHeight)) / (this.data.miniHeaderHeight + this.data.toolbarHeight)
      let isReachTop = opacity == 0 ? true : false
      this.setData({
        scrollHeight: this.data.windowHeight - top,
        headerOpacity: opacity,
        showMiniHeader: isReachTop,
        scrollAble: isReachTop
      })
    },
    updateScrollViewLayout(offsetY: number) {
      let delta = offsetY - this.data.scrollviewStartY
      if (delta > 0) {
        return
      }
      delta = -delta
      if (delta > this.data.headerHeight - this.data.miniHeaderHeight) {
        delta = this.data.headerHeight - this.data.miniHeaderHeight
      }
      
      let opacity = 1 - (delta) / (this.data.headerHeight - this.data.miniHeaderHeight)
      let isReachTop = opacity == 0 ? true : false
      this.setData({
        scrollHeight: this.data.windowHeight - this.data.headerHeight - this.data.toolbarHeight + delta,
        headerOpacity: opacity,
        showMiniHeader: isReachTop,
        scrollAble: isReachTop
      })
    },
    tween(from: number, to: number, duration: number) {
      let interval = this.data.animationInterval
      let count = duration / interval
      let delta = (to-from) / count
      this.tweenUpdate(count, delta, from)
    },
    tweenUpdate(count: number, delta: number, from: number) {
      let interval = this.data.animationInterval
      let that = this
      setTimeout(() => {
        that.updateLayout(from + delta)
        if (count >= 0) {
          that.tweenUpdate(count-1, delta, from + delta)
        }
      }, interval);
    }
  },
})

less

/**index.less**/
.header {
  height: 400px;
  background-color: red;
}
.scrollarea {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: blue;
}
.toolbar {
  height: 100px;
  position: fixed;
  left: 0;
  right: 0;
  background-color: green;
}
.mini-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 200px;
  background-color: cyan;
}
.item {
  width: 670rpx;
  height: 200rpx;
  background-color: yellow;
  margin: 40rpx;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/420454.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软考-计算题

1.二维矩阵转换成一维矩阵 2.算术表达式&#xff1a; 3.计算完成项目的最少时间&#xff1a;之前和的max&#xff08;必须之前的所有环节都完成&#xff09; 松弛时间&#xff1a;最晚开始时间-最早开始时间 最早&#xff1a;之前环节都完成的和的max 最晚&#xff1a;总时间…

LTX Studio开放测试,用户可以通过输入文本来生成超过25秒的微电影视频;人工智能的崛起和局限

&#x1f989; AI新闻 &#x1f680; LTX Studio开放测试&#xff0c;用户可以通过输入文本来生成超过25秒的微电影视频 摘要&#xff1a;LTX Studio是由著名AI平台Lightricks推出的生成式AI电影制作平台。用户可以通过输入文本来生成超过25秒的微电影视频&#xff0c;并且可…

K8s安全一

Kubernetes是一个开源的&#xff0c;用于编排云平台中多个主机上的容器化的应用&#xff0c;目标是让部署容器化的应用能简单并且高效的使用, 提供了应用部署&#xff0c;规划&#xff0c;更新&#xff0c;维护的一种机制。其核心的特点就是能够自主的管理容器来保证云平台中的…

雷达新研社丨宏电雷达水位计化身“智慧管家”,守护滁州城市生命线

城市生命线是维系城市正常运行、满足群众生产生活需要的重要基础设施。为大力推进城市生命线安全工程建设&#xff0c;加快韧性城市建设&#xff0c;滁州市实施了城市生命线安全工程建设项目。 项目包含对全市1650.5公里排水安全监测感知网的建设&#xff0c;宏电股份作为智慧…

第四十七回 一丈青单捉王矮虎 宋公明二打祝家庄-强大而灵活的python装饰器

四面全是埋伏&#xff0c;宋江和众人一直绕圈跑不出去。正在慌乱之时&#xff0c;石秀及时赶到&#xff0c;教大家碰到白杨树就转弯走。走了一段时间&#xff0c;发现围的人越来越多&#xff0c;原来祝家庄以灯笼指挥号令。花荣一箭射下来红灯龙&#xff0c;伏兵自己就乱起来了…

仿牛客网项目---显示评论和添加评论功能的实现

这篇文章&#xff0c;我来介绍一下我的项目中的另外一个功能&#xff1a;显示评论和添加评论。 其实这两个功能都不怎么重要&#xff0c;我感觉最重要的应该是用户注册登录功能&#xff0c;这个也了解一下&#xff0c;知道这么一回事儿就好。 首先设计DAO层。 Mapper public …

LNMP架构介绍及配置--部署Discuz社区论坛与wordpress博客

一、LNMP架构定义 1、LNMP定义 LNMP&#xff08;Linux Nginx Mysql Php&#xff09;是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写&#xff1b;Linux系统下NginxMySQLPHP这种网站服务器架构。 Linux是一类Unix计算机操作系统的统称&#xff0c;是目…

Qt程序设计-指南针自定义控件实例

本文讲解Qt指南针自定义控件实例。 效果演示 创建指南针类 #ifndef COMPASS_H #define COMPASS_H#include <QWidget> #include <QWidget> #include <QTimer> #include <QPainter> #include <QPen> #include <QDebug> #include <QtMat…

【激光SLAM】基于已知位姿的构图算法 (Grid-based)

文章目录 地图分类概念 覆盖栅格建图算法栅格地图的特征数学描述假设 算法流程激光雷达的逆观测模型 计数(Count Model)建图算法概念数学描述观测模型地图估计 地图分类 概念 地图即为环境的空间模型。环境地图是机器人进行定位和规划的前提。定位可以用特征地图&#xff08;…

java-ssm-jsp房屋中介服务平台的设计与实现

java-ssm-jsp房屋中介服务平台的设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全

28.HarmonyOS App(JAVA)多页签的实现(Tab)

HarmonyOS App(JAVA)多页签的实现&#xff08;Tab&#xff09; 页面可左右滑动&#xff0c;点击界面1,2,3切换到对应界面 PageSlider的创建和使用 在layout目录下的xml文件中创建PageSlider。 <PageSlider ohos:id"$id:page_slider" ohos:height"300vp&…

Java编程实战:小区管理系统的设计与实现

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

MySQL之索引详解

华子目录 索引概述优缺点 索引的原理索引的设计原则索引结构B-tree&#xff08;多路平衡查找树&#xff09;BtreeHash 为什么InnoDB存储引擎选择Btree&#xff1f;索引分类聚集索引选取规则 单列索引和多列索引前缀索引创建索引1.创建表时创建索引2.在已经存在的表上创建索引3.…

Muduo库核心代码及优秀编程细节剖析

一、前言&#xff1a; Muduo库是陈硕个人开发的Tcp网络编程库&#xff0c;支持Reactor模型。这篇博文对Muduo库中的Multi-reactor架构代码进行逻辑梳理&#xff0c;同时认真剖析了作者每一处精妙的代码设计思想。 目前我只重构并剖析了Muduo库中的核心部分&#xff0c;即Mult…

了解处理器

了解处理器 摘要写在前面1. 计算机简介1.1.计算机发展简史1.2.计算机分类1.3.PC机结构 2.初识处理器2.1.处理器的硬件模型2.2.处理器的编程模型2.3.处理器的分层模型2.4.如何选择处理器 3.指令集体系结构3.1.处理器编程模型3.2.指令集发展历程3.3.指令集分类3.4.汇编语言格式3.…

第三百七十六回

文章目录 1 .概念介绍2. 实现方法3. 示例代码 我们在上一章回中介绍了在页面之间共传递数据相关的内容&#xff0c;本章回中将介绍如何拦截路由.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 .概念介绍 本章回中介绍的路由拦截是指在路由运行过程中&#xff0c;对路由做…

Java进阶(锁)——锁的升级,synchronized与lock锁区别

目录 引出Java中锁升级synchronized与lock锁区别 缓存三兄弟&#xff1a;缓存击穿、穿透、雪崩缓存击穿缓存穿透缓存雪崩 总结 引出 Java进阶&#xff08;锁&#xff09;——锁的升级&#xff0c;synchronized与lock锁区别 Java中锁升级 看一段代码&#xff1a; public class…

Python学习 day06(类、对象、构造方法、私有方法、继承

类 程序中数据的组织多种多样&#xff0c;如果我们简单用变量来记录&#xff0c;就会混乱、不统一&#xff0c;如下所示&#xff1a; 类比现实中的表格&#xff0c;我们可以用类来组织数据&#xff0c;如下&#xff1a; 类的定义和使用 类中的变量叫做成员变量&#xff0c;类中…

mysql,for循环执行sql

遇到一个问题&#xff0c;我需要模拟上百万数据来优化sql&#xff0c;线上数据down不下来&#xff0c;测试库又没有&#xff0c;写代码执行要么慢要么就是sql语句太长。 于是&#xff0c;直接用mysql自带的功能去实现&#xff01; 简单而简单 mysql可以for循环&#xff1f;没…

python中版本,操作系统等问题汇总

1. linux源码部署到windows 1.1ModuleNotFoundError: No module named pwd 这个问题&#xff0c;是因为源码是给linux的。这里在windows中&#xff0c;没有该命令。 解决方法之一&#xff0c;在相应的环境目录中&#xff0c;如图中<MetaGPTenv>虚拟环境中&#xff0c;在…