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. 最长公共前缀 算法讲解 我们使用当前第一个字符串中的与后面的字符串作比较,如果第一个字符串中的字符没有出现在后面的字符串中,我们就直接返回;反之当容器中的所有字符串都遍历完成,说明所有的字符串都在该位置…...
(三)JVM实战——对象的内存布局与执行引擎详解
对象的内存布局 对象的实例化 对象的创建方式 - new的方式 - Class的newInstance():反射的方式 - Construct的newInstance() - clone:实现Cloneable接口,默认浅拷贝 - 使用反序列化:将二进制流转化为内存对象 创建对象的步骤 - 判断对象对应的类是否加载、链接、初…...
微信视频号如何变现呢,视频号涨粉最快方法
今天给大家带来的是视频号分成计划 视频号流量主这个项目,可以说这是目前的一个蓝海赛道,做的人也少,外面开的培训也很少,作为副业还是比较适合个人的,如果想批量操作这个项目,也比较适合工作室的。而且这…...
数智先锋 | 多场景数据治理案例,释放数据要素生产力
数据作为第五大生产要素,成为释放新质生产力的关键基础。 当前各个行业数字化建设如火如荼,全力挖掘数据价值以驱动行业高质量应用发展。数据治理成为数据要素价值发挥的重要基础和前提。 数据治理不单是技术问题,不是依赖工具就能解决的&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,把前面提到的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 …...
抖音视频评论区用户采集 根据视频链接批量获取用户信息
要批量获取抖音视频评论区用户的信息,可以通过抖音开放平台的接口来实现。 首先,你需要在抖音开放平台注册开发者账号,并创建一个应用。然后,使用抖音开放平台提供的接口,可以根据视频链接获取视频的详细信息…...
C++ 多态(一)
一、多态定义 同一种操作作用于不同的对象时,可以产生不同的行为。在面向对象编程中,多态性是指通过继承和重写实现的,同一个方法在不同的子类中可以表现出不同的行为。多态性可以提高代码的灵活性和可扩展性,使得程序更易于维护…...
[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-函数式编程-函数对象
定义 什么是合格的函数?无论多少次执行函数,只要输入一样,输出就不会改变 对象方法的简写 其实在类中,我们很多参数中都有一个this,被隐藏传入了 函数也可以作为对象传递,lambda就是很好的例子 函数式接口中…...
致远oa实时获取第三方自定义组件实现
背景 最近的一个需求不好处理,甲方没有准确的数据支撑,各种问题踢皮球,所以有时间实现一个实时获取数据的组件 需求 为了实现方便,封装了一个第三方数据实时展示的组件 只要修改配置,就可以实现字段的删除增加&…...
【Linux-点灯烧录-SD卡/USB烧写】
目录 1. 烧写方式2. 烧写之代码编译2.1 led.s->led.o2.2 led.o->led.elf2.3 led.elf->led.bin2.4 反汇编:led.elf->led.dis 3. 烧写之烧录到SD卡上:3.1 开启烧录软件权限:3.2 确定SD卡的格式:FAT323.3 烧录到SD卡上3.…...
PostgreSQL自带的命令行工具06- pg_isready
PostgreSQL自带的命令行工具06- pg_isready 基础信息 OS版本:Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本:16.2 pg软件目录:/home/pg16/soft pg数据目录:/home/pg16/data 端口:5777pg_isready 是 Po…...
【请投票】嘉立创EDA中LED发光二极管是否应有统一的引脚定义?
LED发光二极管的引脚定义应该是唯一的吗? 从下面原理图可以看到,器件型号仅尾缀不同,R代表RED红色发光二极管,W代表WHITE指白色发光二极管,是同一家制造商KENTO, 左侧红色发光二极管的1脚是阴极K,2脚是阳极…...
LT6911UXB HDMI2.0 至四端口 MIPI DSI/CSI,带音频 龙迅方案
1. 描述LT6911UXB 是一款高性能 HDMI2.0 至 MIPI DSI/CSI 转换器,适用于 VR、智能手机和显示应用。HDMI2.0 输入支持高达 6Gbps 的数据速率,可为4k60Hz视频提供足够的带宽。此外,数据解密还支持 HDCP2.2。对于 MIPI DSI / CSI 输出࿰…...
网络培训议题@2
目录 1. 如何通过IP和掩码确定网关:2. 网络路由的意义和配置方法:3. 网络Bond模式的区别和配置场景:4. 堆叠、VLAN、Trunk、聚合的意义:5. 虚拟机环境下VIP配置和常见问题:6. VXLAN拓展: 1. 如何通过IP和掩…...
linux文本三剑客之sed
目录 1、sed特点 1)sed命令格式 2)sed命令核心功能"增删改查" 2、sed命令执行过程 3、sed核心应用 1)sed-查找p 2)sed-删除d 3)sed-增加cai 4) sed-替换s 1、sed特点 sed stream editor 流编辑器…...
nginx封禁恶意IP
网络攻击时有发生 TCP洪水攻击、注入攻击、DOS等比较难防的有DDOS等 为了数据安全,防止对手爬虫恶意爬取,封禁IP 一般封禁ip linux server层面封IP:iptablesnginx层面封IP,方式多种(但req还是会打进来,让…...
FPGA新手必看:用Verilog手搓一个SPI Master控制器(Mode 0/3实战)
FPGA实战:从零构建SPI Master控制器的Verilog实现指南 1. 初识SPI协议与FPGA开发环境搭建 对于刚接触FPGA和数字电路设计的工程师来说,SPI(Serial Peripheral Interface)协议是一个理想的起点。这种同步串行通信协议广泛应用于传感…...
7B秒杀70B!大模型微调秘籍全解:从理论到实战,玩转高效适配!
本文系统介绍了大模型微调的理论框架与实践流程。阐述了微调的必要性,即弥补通用大模型在领域知识、输出格式及行为对齐上的不足,并说明微调效果可超越更大参数的未微调模型。文章深入解析了微调原理,对比了全参数微调与高效微调(…...
瑞芯微(EASY EAI)RV1126B TF卡电路
1. TF卡电路RV1126B核心板集成了1个SDMMC控制器和1个SDIO控制器,均可支持SDIO3.0协议,以及MMC V4.51协议。4线的数据总线宽度支持SDR104模式,速率达到200MHz。SDMMC控制器是由PMIC单独供电,可以动态的在1.8V和3.3V之间调节&#x…...
本地部署dify的Excel提取器出现以下问题:Error extracting from Excel workbook: Request URL is missing an ‘http://’ or
本地部署dify的Excel提取器出现以下问题:An error occurred in the samanhappy/excel_process/excel_process, please contact the author of samanhappy/excel_process/excel_process for help, error type: Exception, error details: Error extracting from Exce…...
K-Means聚类选K避坑指南:当肘部法则“失灵”,轮廓系数如何救场?
K-Means聚类选K避坑指南:当肘部法则"失灵",轮廓系数如何救场? 在数据科学实践中,K-Means算法因其简洁高效而广受欢迎,但确定最佳聚类数K却常让从业者陷入困境。当面对高维、噪声多或分布不平衡的真实业务数据…...
光模块PCB设计学习记录01
/*光模块布局,有错误可以指出,有不足可以补充*/ 光模块PCB布局规划 01导入板框与结构约束导入 这里的outline板框一般由机械提供.dxf文件,板框决定PCB尺寸、器件可用区域和接口位置;成功导入dxf文件后,打开Board Geo…...
Seraphine英雄联盟战绩查询工具终极指南:智能排位助手完全教程
Seraphine英雄联盟战绩查询工具终极指南:智能排位助手完全教程 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 你是否在英雄联盟排位赛中经常因为BP阶段手忙脚乱而错失先机?是否希望快…...
多智能体协同控制未来的前景和方向如何?
在AI技术快速演进的今天,单一智能体已难以满足企业复杂业务场景的需求,多智能体协同正成为行业关注的焦点,它通过多个智能体分工协作、动态交互,形成更强大、更灵活的数字员工团队,有望重塑企业运营模式,推…...
2026本地视频怎么去水印?5款免费去水印软件对比和实用方法指南
很多人都遇到过这个问题:辛辛苦苦保存下来的视频、素材库里的片段,上面都贴了水印,想要二次编辑或重新发布时,这些水印就成了"眼中钉"。本地视频怎么去水印?2026年有哪些靠谱的免费去水印方法?今…...
从医院PACS到你的Python脚本:手把手教你用pydicom库读写和修改DICOM文件
从医院PACS到Python脚本:pydicom实战医学影像处理指南 医学影像数据正以每年30%的速度增长,而DICOM作为医疗影像存储与传输的国际标准,承载着CT、MRI等设备产生的海量数据。在临床研究、AI模型训练和医疗信息化建设中,开发者经常需…...
