当前位置: 首页 > news >正文

Swift手撸轮播效果

一、创建ScrollView

@objcMembers class LSLottieAnimView: UIView, UIScrollViewDelegate {private var scrollView: UIScrollView = UIScrollView()func addScrollView() {scrollView.showsHorizontalScrollIndicator = falsescrollView.isPagingEnabled = true// 自定义framescrollView.frame = CGRect(x: 0, y: 0, width: 100, height: 100)scrollView.delegate = self// 此处创建了三个子view的宽度scrollView.contentSize = CGSize(width: scrollView.frame.width * CGFloat(3), height: scrollView.frame.height)let u1 = UIView()u1.frame = scrollView.boundsu1.backgroundColor = .blacklet u2 = UIView()u2.frame = scrollView.boundsu2.backgroundColor = .greenlet u3 = UIView()u3.frame = scrollView.boundsu3.backgroundColor = .yellowscrollView.addSubview(u1)scrollView.addSubview(u2)scrollView.addSubview(u3)UIApplication.shared.keyWindow?.rootViewController?.view.addSubview(scrollView)// 添加拖拽手势识别器let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:)))scrollView.addGestureRecognizer(panGesture)}
}

二、处理手势

@objc func handlePan(_ gesture: UIPanGestureRecognizer) {let scrollView = gesture.view as! UIScrollViewlet translation = gesture.translation(in: scrollView)// let count = scrollView.subviews.count - 1 - 1;// 禁止回弹if (scrollView.contentOffset.x <= 0 && translation.x > 0) || (Int(scrollView.frame.width) * count <= Int(scrollView.contentOffset.x) && translation.x < 0) {return}// 当setContentOffset的动画未完成时,此时isDecelerating为trueif scrollView.isDecelerating || !scrollView.isScrollEnabled {return}switch gesture.state {// case .began:// 如果开启轮播,则停止自动轮播// scrollView.layer.removeAllAnimations()case .changed:// 根据手势的偏移量进行滚动if scrollView.contentOffset.x - translation.x <= 0 {scrollView.contentOffset.x = 0} else if scrollView.contentOffset.x - translation.x >= scrollView.frame.width * CGFloat(count) {scrollView.contentOffset.x = scrollView.frame.width * CGFloat(count)} else {scrollView.contentOffset.x -= translation.x}case .ended, .cancelled, .failed:// 获取滚动视图当前的页索引let pageIndex = Int(scrollView.contentOffset.x / scrollView.frame.width)// 修改后的页面索引var willPageIndex = pageIndex// 根据手势的速度和偏移量来判断是否切换到上一页或下一页let velocity = gesture.velocity(in: scrollView)if velocity.x > 0 {// 向右滑动} else if velocity.x < 0 {// 向左滑动if pageIndex < count {willPageIndex = pageIndex + 1}} else {// 根据偏移量判断是否切换到上一页或下一页if translation.x < -scrollView.frame.width / 2 && pageIndex < count {willPageIndex = pageIndex + 1} else if translation.x > scrollView.frame.width / 2 && pageIndex > 0 {willPageIndex = pageIndex - 1}}// 只有修改后才需要调用setContentOffset,否则会出现scrollViewDidEndScrollingAnimation不调用的情况if (scrollView.contentOffset.x != CGFloat(willPageIndex) * scrollView.frame.width) {scrollView.setContentOffset(CGPoint(x: CGFloat(willPageIndex) * scrollView.frame.width, y: 0), animated: true)scrollView.isScrollEnabled = false}default:break}// 重置手势的偏移量gesture.setTranslation(.zero, in: scrollView)
}// MARK: UIScrollViewDelegate
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {scrollView.isScrollEnabled = true
}

三、注意事项

1. 如果需要回弹,只需要修改如下代码即可
// 注释如下代码
if (scrollView.contentOffset.x <= 0 && translation.x > 0) || (Int(scrollView.frame.width) * count <= Int(scrollView.contentOffset.x) && translation.x < 0) {return
}// 修改成如下代码case .changed:
//            // 根据手势的偏移量进行滚动
//            if scrollView.contentOffset.x - translation.x <= 0 {
//                scrollView.contentOffset.x = 0
//            } else if scrollView.contentOffset.x - translation.x >= scrollView.frame.width * CGFloat(count) {
//                scrollView.contentOffset.x = scrollView.frame.width * CGFloat(count)
//            } else {scrollView.contentOffset.x -= translation.x
//            }2. 在调用setContentOffset且animated为true时,需要考虑将isScrollEnabled设置为false,等到动画完成后(scrollViewDidEndScrollingAnimation)将isScrollEnabled恢复到true,否则在动画期间仍然可以拖拽
3. 在调用setContentOffset时,如果值和之前相同,则不会触发scrollViewDidEndScrollingAnimation

相关文章:

Swift手撸轮播效果

一、创建ScrollView objcMembers class LSLottieAnimView: UIView, UIScrollViewDelegate {private var scrollView: UIScrollView UIScrollView()func addScrollView() {scrollView.showsHorizontalScrollIndicator falsescrollView.isPagingEnabled true// 自定义framesc…...

数据分析——业务数据描述

业务数据描述 前言一、数据收集数据信息来源企业内部数据源市场调查数据源公共数据源和第三方数据源 二、公司内部数据客户资料数据销售明细数据营销活动数据 三、市场调查数据观察法提问法实验法 四、公共数据五、第三方数据六、数据预处理七、数据清洗丢弃部分数据补全缺失的…...

【哈希表】Leetcode 14. 最长公共前缀

题目讲解 14. 最长公共前缀 算法讲解 我们使用当前第一个字符串中的与后面的字符串作比较&#xff0c;如果第一个字符串中的字符没有出现在后面的字符串中&#xff0c;我们就直接返回&#xff1b;反之当容器中的所有字符串都遍历完成&#xff0c;说明所有的字符串都在该位置…...

(三)JVM实战——对象的内存布局与执行引擎详解

对象的内存布局 对象的实例化 对象的创建方式 - new的方式 - Class的newInstance():反射的方式 - Construct的newInstance() - clone:实现Cloneable接口,默认浅拷贝 - 使用反序列化&#xff1a;将二进制流转化为内存对象 创建对象的步骤 - 判断对象对应的类是否加载、链接、初…...

微信视频号如何变现呢,视频号涨粉最快方法

今天给大家带来的是视频号分成计划 视频号流量主这个项目&#xff0c;可以说这是目前的一个蓝海赛道&#xff0c;做的人也少&#xff0c;外面开的培训也很少&#xff0c;作为副业还是比较适合个人的&#xff0c;如果想批量操作这个项目&#xff0c;也比较适合工作室的。而且这…...

数智先锋 | 多场景数据治理案例,释放数据要素生产力

数据作为第五大生产要素&#xff0c;成为释放新质生产力的关键基础。 当前各个行业数字化建设如火如荼&#xff0c;全力挖掘数据价值以驱动行业高质量应用发展。数据治理成为数据要素价值发挥的重要基础和前提。 数据治理不单是技术问题&#xff0c;不是依赖工具就能解决的&a…...

UE5 audio capture 回声问题 ||在安卓上有爆鸣声

参考视频 0.基本步骤 【UE4_蓝图】录制麦克风声音/系统声音并输出保存WAV文件_ue4录音-CSDN博客 1.步骤 1.创建Sound Submix A 2. 右键新建Sound Submix B 3.把B的两个参数调为-96 4.audio capture的Base Submix&#xff0c;把前面提到的A赋值进去 5.开始录制输出和完成录制…...

第 10 场蓝桥杯小白入门赛题解

1.五一礼物【算法赛】 - 蓝桥云课 (lanqiao.cn) #include <iostream> using namespace std; int main() {cout<<"51"<<endl;return 0; }2.合成贤者之石【算法赛】 - 蓝桥云课 (lanqiao.cn) 假设黄水晶的个数是 x x x,那蓝水晶个数肯定是 x − 1 …...

抖音视频评论区用户采集 根据视频链接批量获取用户信息

要批量获取抖音视频评论区用户的信息&#xff0c;可以通过抖音开放平台的接口来实现。 首先&#xff0c;你需要在抖音开放平台注册开发者账号&#xff0c;并创建一个应用。然后&#xff0c;使用抖音开放平台提供的接口&#xff0c;可以根据视频链接获取视频的详细信息&#xf…...

C++ 多态(一)

一、多态定义 同一种操作作用于不同的对象时&#xff0c;可以产生不同的行为。在面向对象编程中&#xff0c;多态性是指通过继承和重写实现的&#xff0c;同一个方法在不同的子类中可以表现出不同的行为。多态性可以提高代码的灵活性和可扩展性&#xff0c;使得程序更易于维护…...

[Linux][网络][TCP][一][TCP基础][TCP报头]详细讲解

目录 1.TCP头部格式2.TCP协议的特点3.TCP如何封装与分用4.通过序列号和确认应答号提高可靠性1.32位序列号2.32位确认应答号3.保证可靠性4.为什么序列号和确认应答号是单独的字段 5.窗口大小1.TCP的发送和接收缓冲区2.窗口大小 6.连接管理机制 1.TCP头部格式 TCP全称为"传输…...

java-函数式编程-函数对象

定义 什么是合格的函数&#xff1f;无论多少次执行函数&#xff0c;只要输入一样&#xff0c;输出就不会改变 对象方法的简写 其实在类中&#xff0c;我们很多参数中都有一个this&#xff0c;被隐藏传入了 函数也可以作为对象传递&#xff0c;lambda就是很好的例子 函数式接口中…...

致远oa实时获取第三方自定义组件实现

背景 最近的一个需求不好处理&#xff0c;甲方没有准确的数据支撑&#xff0c;各种问题踢皮球&#xff0c;所以有时间实现一个实时获取数据的组件 需求 为了实现方便&#xff0c;封装了一个第三方数据实时展示的组件 只要修改配置&#xff0c;就可以实现字段的删除增加&…...

【Linux-点灯烧录-SD卡/USB烧写】

目录 1. 烧写方式2. 烧写之代码编译2.1 led.s->led.o2.2 led.o->led.elf2.3 led.elf->led.bin2.4 反汇编&#xff1a;led.elf->led.dis 3. 烧写之烧录到SD卡上&#xff1a;3.1 开启烧录软件权限&#xff1a;3.2 确定SD卡的格式&#xff1a;FAT323.3 烧录到SD卡上3.…...

PostgreSQL自带的命令行工具06- pg_isready

PostgreSQL自带的命令行工具06- pg_isready 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;5777pg_isready 是 Po…...

【请投票】嘉立创EDA中LED发光二极管是否应有统一的引脚定义?

LED发光二极管的引脚定义应该是唯一的吗&#xff1f; 从下面原理图可以看到&#xff0c;器件型号仅尾缀不同,R代表RED红色发光二极管&#xff0c;W代表WHITE指白色发光二极管&#xff0c;是同一家制造商KENTO&#xff0c; 左侧红色发光二极管的1脚是阴极K&#xff0c;2脚是阳极…...

LT6911UXB HDMI2.0 至四端口 MIPI DSI/CSI,带音频 龙迅方案

1. 描述LT6911UXB 是一款高性能 HDMI2.0 至 MIPI DSI/CSI 转换器&#xff0c;适用于 VR、智能手机和显示应用。HDMI2.0 输入支持高达 6Gbps 的数据速率&#xff0c;可为4k60Hz视频提供足够的带宽。此外&#xff0c;数据解密还支持 HDCP2.2。对于 MIPI DSI / CSI 输出&#xff0…...

网络培训议题@2

目录 1. 如何通过IP和掩码确定网关&#xff1a;2. 网络路由的意义和配置方法&#xff1a;3. 网络Bond模式的区别和配置场景&#xff1a;4. 堆叠、VLAN、Trunk、聚合的意义&#xff1a;5. 虚拟机环境下VIP配置和常见问题&#xff1a;6. VXLAN拓展&#xff1a; 1. 如何通过IP和掩…...

linux文本三剑客之sed

目录 1、sed特点 1&#xff09;sed命令格式 2&#xff09;sed命令核心功能"增删改查" 2、sed命令执行过程 3、sed核心应用 1&#xff09;sed-查找p 2&#xff09;sed-删除d 3&#xff09;sed-增加cai 4) sed-替换s 1、sed特点 sed stream editor 流编辑器…...

nginx封禁恶意IP

网络攻击时有发生 TCP洪水攻击、注入攻击、DOS等比较难防的有DDOS等 为了数据安全&#xff0c;防止对手爬虫恶意爬取&#xff0c;封禁IP 一般封禁ip linux server层面封IP&#xff1a;iptablesnginx层面封IP&#xff0c;方式多种&#xff08;但req还是会打进来&#xff0c;让…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法

使用 ROS1-Noetic 和 mavros v1.20.1&#xff0c; 携带经纬度海拔的话题主要有三个&#xff1a; /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码&#xff0c;来分析他们的发布过程。发现前两个话题都对应了同一…...

安宝特方案丨从依赖经验到数据驱动:AR套件重构特种装备装配与质检全流程

在高压电气装备、军工装备、石油测井仪器装备、计算存储服务器和机柜、核磁医疗装备、大型发动机组等特种装备生产型企业&#xff0c;其产品具有“小批量、多品种、人工装配、价值高”的特点。 生产管理中存在传统SOP文件内容缺失、SOP更新不及、装配严重依赖个人经验、产品装…...

浏览器兼容-polyfill-本地服务-优化

babel和webpack结合 npx babel src --out-dir dist --presetsbabel/preset-env 这是把src下面的东西都用babel转化一下 webpack可以和babel结合使用&#xff0c;首先下载一个这东西&#xff1a; npm install babel-loader -D webpack配置&#xff1a; const path requir…...