「iOS」UI——无限轮播图实现与UIPageControl运用

「OC」UI

文章目录

  • 「OC」UI
    • 无限轮播图的实现以及UIPageControl的实际运用
      • 明确要求
      • 简单滚动视图的实现
        • UIPageControl的实现
        • 设置NSTimer实现自动移动
        • 补充实现
    • 进行无限滚动视图的修改
      • 思路
      • 实现
    • 完整代码展示

无限轮播图的实现以及UIPageControl的实际运用

明确要求

我们要实现一个能够进行无限滚动播放的视图程序,首先需要实现的是一个简单的滚动图片视图,在视图之中添加相关的UIPageControl的控件,让我们能够知道我们当前图片是处在滚动页面的哪个位置上。在实现简单滚动视图的基础上进行修改,使其实现无限轮播的功能。

简单滚动视图的实现

提到滚动视图,我们就会想起刚刚学习的UIScrollView,使用UIImageVIew布局在UIScrollView之中,我们写给其写个函数将UIScrollView的框架封装起来

- (void)setupScrollView {//进行初始化操作self.scrollView = [[UIScrollView alloc] init];self.scrollView.frame = CGRectMake(0, 80, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 320);//设置整页滚动self.scrollView.pagingEnabled = YES;self.scrollView.scrollEnabled = YES;self.scrollView.delegate = self;//由于我们使用UIPageControl所以,self.scrollView.showsHorizontalScrollIndicator = NO;CGFloat h = [UIScreen mainScreen].bounds.size.height - 320;CGFloat w = [UIScreen mainScreen].bounds.size.width;self.scrollView.contentSize = CGSizeMake(w * 5, h); // 五个图片设置五个宽度for (int i = 0; i < 5; i++) {NSString *name = [NSString stringWithFormat:@"%d.jpg", i];UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:name]];imageView.frame = CGRectMake(i * w, 0, w, h);[self.scrollView addSubview:imageView];}[self.view addSubview:self.scrollView];
}
UIPageControl的实现

对于UIPageControl的实现十分简单,实现如下

- (void)setupPageControl {self.pageControl = [[UIPageControl alloc] init];//设置PageControl与滚动视图对齐self.pageControl.frame = CGRectMake(0, CGRectGetMaxY(self.scrollView.frame) - 20, CGRectGetWidth(self.scrollView.frame), 20);self.pageControl.numberOfPages = 5;//设置初始页面self.pageControl.currentPage = 0;self.pageControl.pageIndicatorTintColor = [UIColor redColor];self.pageControl.currentPageIndicatorTintColor = [UIColor blueColor];self.pageControl.userInteractionEnabled = NO;[self.view addSubview:self.pageControl];
}

那么对于当前位置的UIPageControl显示的变化,我们也要控制下面显示的变化,对于我们显示的变化,我们可以进行更深入的控制,,我们在当前偏移量添加半个视图宽度,这样当我们当前图片偏移量超过半个宽度之后,UIPageControl的位置就会发生变化,就会显得我们的显示更加智能,我们将代码写在scrollViewDidScroll:(UIScrollView *)scrollView之中,这个函数是当UIScrollView发生滚动就会调用。

(void)scrollViewDidScroll:(UIScrollView *)scrollView {CGFloat offSetX = scrollView.contentOffset.x;//求取当前页CGFloat pageWidth = scrollView.frame.size.width;int currentPage = floor((offSetX - pageWidth / 2) / pageWidth) + 1;//控制UIPageControl 的当前页self.pageControl.currentPage = currentPage;
}
设置NSTimer实现自动移动

我们可以设置一个定时器,使其不断进行视图的替换,我们设置间隔为2秒,每两秒调用翻页的方法,对滚动视图界面进行翻页,需要特殊判断的是,当移动到最后的时候,我们需要将其调到第一个视图。

- (void)setupTimer {//创建定时器_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];}- (void)nextPage {NSInteger page = self.pageControl.currentPage;if (page == self.pageControl.numberOfPages - 1) {page = 0;} else {page++;}CGFloat offSetX = page * self.scrollView.frame.size.width;[self.scrollView setContentOffset:CGPointMake(offSetX, 0) animated:YES];}
补充实现

当我们在使用鼠标对滚动视图进行抓取移动时,由于定时器的存在,视图仍然会进行移动,因此,我们为了方便操作,我们可以在当鼠标进行点击时,将计时器取消,当鼠标结束拖拽时重新创建计时器,我们就需要用上两个函数。

  • -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView :当开始进行拖拽
  • -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate:当拖拽结束时

实现如下:

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {if ([self.timer isValid]) {[self.timer invalidate];self.timer = nil;}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{if (![_timer isValid]) {_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];}
}

Jun-19-2024 00-02-48

进行无限滚动视图的修改

思路

我们在对其进行无限滚动视图的修改,首先我们要了解无限滚动视图的如何进行实现的,我们需要在原本的滚动视图之中,左右各自添加一个新的视图。这是为什么呢?

我们将五张图片简化为三张图片,形状如下:

image-20240618235611013

通过观察我们的原理图,我们可以很清晰的了解我们需要实现的功能:当我们的滚动视图处于第二张视图的位置(第一张pic1的位置)时,向前滑动所展示的图片是png3;当处于倒数第二张视图的位置(第二张pic3)时,向后滚动要展现的图片是pic1。了解轮播图是这个结构之后,我们就要思考如何去实现这个功能,我们使用偏移量进行解决,当我们即将翻到从pic1翻到pic3(情况1)或者pic3直接翻到pic1(情况2)的时候,我们从偏移量之中读取这种情况,然后进行滚动视图的变化,当情况1出现时,就会将当前视图从pic1的位置直接跳到标红的pic3的位置:情况2同理视图就会从pic3跳转到标红的pic1。由于动画效果的存在,我们进行滑动的时候,并不会在显示之中发现视图变化的不自然。

实现

我们对以上的程序进行修改,由于是五张图片,那么我们在左右两边多添加两张图片,我们称第一张和最后一张图片为实现无限滚动视图的假图,我们对框架内的函数进行修改,此外我们还需要将滚动视图的定位定位至pic1处。

  • ScrollView
- (void)setupScrollView {self.scrollView = [[UIScrollView alloc] init];self.scrollView.frame = CGRectMake(0, 80, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 320);self.scrollView.pagingEnabled = YES;self.scrollView.scrollEnabled = YES;self.scrollView.delegate = self;self.scrollView.showsHorizontalScrollIndicator = NO;CGFloat h = [UIScreen mainScreen].bounds.size.height - 320;CGFloat w = [UIScreen mainScreen].bounds.size.width;self.scrollView.contentSize = CGSizeMake(w * 7, h); // 包括两个额外的页面for (int i = 0; i < 7; i++) {NSString *name;if (i == 0) {name = @"5.jpg"; // 第一页前面的假页} else if (i == 6) {name = @"1.jpg"; // 最后一页后面的假页} else {name = [NSString stringWithFormat:@"%d.jpg", i];}UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:name]];imageView.frame = CGRectMake(i * w, 0, w, h);[self.scrollView addSubview:imageView];}// 设置默认显示的页面(实际第一页)[self.scrollView setContentOffset:CGPointMake(w, 0) animated:NO];[self.view addSubview:self.scrollView];
}
  • scrollViewDidScroll:(UIScrollView *)scrollView在这个函数之中的内容就是我们实现无限滚动视图的关键,请看代码
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {CGFloat offsetX = scrollView.contentOffset.x;//滚动视图的显示宽度CGFloat pageWidth = scrollView.frame.size.width;//新添加的内容if (offsetX >= pageWidth * 6) {// 滚动到假的最后一页,瞬间跳到实际第一页[self.scrollView setContentOffset:CGPointMake(pageWidth, 0) animated:NO];} else if (offsetX <= 0) {// 滚动到假的第一页,瞬间跳到实际最后一页[self.scrollView setContentOffset:CGPointMake(pageWidth * 5, 0) animated:NO];}// 更新UIPageControl的当前页NSInteger currentPage = (scrollView.contentOffset.x + pageWidth / 2) / pageWidth;//当翻到假页时对pagecontrol进行修改,使其符合要求if (currentPage == 0) {self.pageControl.currentPage = 4;} else if (currentPage == 6) {self.pageControl.currentPage = 0;} else {self.pageControl.currentPage = currentPage - 1;}
}
  • 在我们使用翻页的方法也需要进行一点点的改变,我们要将page的偏移量加一。在这里还有一个小细节,由于无限滚动视图的实现,我们不再需要对最后一张视图进行特判,我们只需要在每次调用的时候然page++就可以了。
- (void)nextPage {NSInteger page = self.pageControl.currentPage;if (page == self.pageControl.numberOfPages - 1) {page = 0;} else {page++;}CGFloat offsetX = (page + 1) * self.scrollView.frame.size.width; // 偏移量加1,因为第1页是假的[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}

完整代码展示

#import "ViewController.h"@interface ViewController () <UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
@property (nonatomic, strong) NSTimer *timer;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];[self setupScrollView];[self setupPageControl];[self setupTimer];
}- (void)setupScrollView {self.scrollView = [[UIScrollView alloc] init];self.scrollView.frame = CGRectMake(0, 80, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height - 320);self.scrollView.pagingEnabled = YES;self.scrollView.scrollEnabled = YES;self.scrollView.delegate = self;self.scrollView.showsHorizontalScrollIndicator = NO;CGFloat h = [UIScreen mainScreen].bounds.size.height - 320;CGFloat w = [UIScreen mainScreen].bounds.size.width;self.scrollView.contentSize = CGSizeMake(w * 7, h); // 包括两个额外的页面for (int i = 0; i < 7; i++) {NSString *name;if (i == 0) {name = @"5.jpg"; // 第一页前面的假页} else if (i == 6) {name = @"1.jpg"; // 最后一页后面的假页} else {name = [NSString stringWithFormat:@"%d.jpg", i];}UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:name]];imageView.frame = CGRectMake(i * w, 0, w, h);[self.scrollView addSubview:imageView];}// 设置默认显示的页面(实际第一页)[self.scrollView setContentOffset:CGPointMake(w, 0) animated:NO];[self.view addSubview:self.scrollView];
}- (void)setupPageControl {self.pageControl = [[UIPageControl alloc] init];self.pageControl.frame = CGRectMake(0, CGRectGetMaxY(self.scrollView.frame) - 20, CGRectGetWidth(self.scrollView.frame), 20);self.pageControl.numberOfPages = 5;self.pageControl.currentPage = 0;self.pageControl.pageIndicatorTintColor = [UIColor redColor];self.pageControl.currentPageIndicatorTintColor = [UIColor blueColor];self.pageControl.userInteractionEnabled = NO;[self.view addSubview:self.pageControl];
}- (void)setupTimer {self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
}- (void)nextPage {NSInteger page = self.pageControl.currentPage;if (page == self.pageControl.numberOfPages - 1) {page = 0;} else {page++;}CGFloat offsetX = (page + 1) * self.scrollView.frame.size.width; // 偏移量加1,因为第1页是假的[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}- (void)scrollViewDidScroll:(UIScrollView *)scrollView {CGFloat offsetX = scrollView.contentOffset.x;CGFloat pageWidth = scrollView.frame.size.width;if (offsetX >= pageWidth * 6) {// 滚动到假的最后一页,瞬间跳到实际第一页[self.scrollView setContentOffset:CGPointMake(pageWidth, 0) animated:NO];} else if (offsetX <= 0) {// 滚动到假的第一页,瞬间跳到实际最后一页[self.scrollView setContentOffset:CGPointMake(pageWidth * 5, 0) animated:NO];}// 更新UIPageControl的当前页NSInteger currentPage = (scrollView.contentOffset.x + pageWidth / 2) / pageWidth;if (currentPage == 0) {self.pageControl.currentPage = 4;} else if (currentPage == 6) {self.pageControl.currentPage = 0;} else {self.pageControl.currentPage = currentPage - 1;}- (void)nextPage {NSInteger page = self.pageControl.currentPage;if (page == self.pageControl.numberOfPages - 1) {page = 0;} else {page++;}CGFloat offsetX = (page + 1) * self.scrollView.frame.size.width; // 偏移量加1,因为第1页是假的[self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
}- (void)scrollViewDidScroll:(UIScrollView *)scrollView {CGFloat offsetX = scrollView.contentOffset.x;CGFloat pageWidth = scrollView.frame.size.width;if (offsetX >= pageWidth * 6) {// 滚动到假的最后一页,瞬间跳到实际第一页[self.scrollView setContentOffset:CGPointMake(pageWidth, 0) animated:NO];} else if (offsetX <= 0) {// 滚动到假的第一页,瞬间跳到实际最后一页[self.scrollView setContentOffset:CGPointMake(pageWidth * 5, 0) animated:NO];}// 更新UIPageControl的当前页NSInteger currentPage = (scrollView.contentOffset.x + pageWidth / 2) / pageWidth;if (currentPage == 0) {self.pageControl.currentPage = 4;} else if (currentPage == 6) {self.pageControl.currentPage = 0;} else {self.pageControl.currentPage = currentPage - 1;}
}
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{if ([_timer isValid]) {[_timer invalidate];_timer = nil;}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{if (![_timer isValid]) {_timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];}
}
@end

完整展示如下:

请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

发表在SIGMOD 2024上的高维向量检索/向量数据库/ANNS相关论文

前言 SIGMOD 2024会议最近刚在智利圣地亚哥结束&#xff0c;有关高维向量检索/向量数据库/ANNS的论文主要有5篇&#xff0c;涉及混合查询&#xff08;带属性或范围过滤的向量检索&#xff09;优化、severless向量数据库优化、量化编码优化、磁盘图索引优化。此外&#xff0c;也…

ES全文检索支持繁简和IK分词检索

ES全文检索支持繁简和IK分词检索 1. 前言2. 引入繁简转换插件analysis-stconvert2.1 下载已有作者编译后的包文件2.2 下载源码进行编译2.3 复制解压插件到es安装目录的plugins文件夹下 3. 引入ik分词器插件3.1 已有作者编译后的包文件3.2 只有源代码的版本3.3 安装ik分词插件 4…

示例:推荐一个基于第三方开源控件库DataGridFilter封装的FilterColumnDataGrid,可以像Excel拥有列头筛选器

一、目的&#xff1a;基于第三方开源控件库DataGridFilter封装的FilterColumnDataGrid&#xff0c;可以像Excel拥有列头筛选器&#xff0c;感兴趣的可以去下方链接地址查看开源控件库地址。本控件封装的目的在于将第三方库的皮肤和样式封装到皮肤库中可统一设置样式&#xff0c…

某md5魔改-js还原

我们先把js 扣下来看一下 整体扣一下 ,运行后发现结果一致。 到这里就结束了吗,不不,这次我们要看到它里面具体的变动 <-_-> 先看一下md5的初步加密流程 void MD5Init(MD5_CTX *context) {context->count[0] = 0;context->count[1] = 0;context->state[0]…

linux 简单使用 sftp 和 lftp命令

目录 一. 环境准备二. sftp命令连接到SFTP服务器三. lftp命令3.1 连接FTP和SFTP服务器3.2 将文件从sftp服务器下载到本地指定目录 四. 通过WinSCP命令行从SFTP服务器获取文件到Windows 一. 环境准备 ⏹在安卓手机上下载个MiXplorer&#xff0c;用作SFTP和FTP服务器 官网: htt…

Typora + Hexo 图片路径问题(Typedown)

文章目录 1. 冲突来源2. 解决思路3. 实现1. typora图片路径2. hexo脚本 1. 冲突来源 Hexo上对于图片在md中的引用&#xff0c;使用了post_asset_folder: true配置&#xff0c;来更好的管理图片。 当一篇名为xxx.md的文章引用1.png图片时&#xff0c;默认让1.png保持在xxx文件夹…

cpolar:通过脚本自动更新主机名称和端口号进行内网穿透【免费版】

cpolar 的免费版经常会重新分配 HostName 和 Port&#xff0c;总是手动修改太过麻烦&#xff0c;分享一下自动更新配置文件并进行内网穿透的方法。 文章目录 配置 ssh config编写脚本获取 csrf_token打开登陆界面SafariChrome 设置别名 假设你已经配置好了服务器端的 cpolar。 …

路由

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 客户端&#xff08;例如浏览器&#xff09;把请求发送给 Web 服务器&#xff0c;Web 服务器再把请求发送给 Flask程序实例。程序实例需要知道对每个U…

oracle 外连接(+)和left join用法

案例1&#xff1a; select count(1) FROM TFUNDINFO A, TFUNDTYPE B WHERE A.VC_FUNDCODEB.VC_FUNDCODE() select count(1) FROM TFUNDINFO A, TFUNDTYPE B WHERE A.VC_FUNDCODEB.VC_FUNDCODE SELECT count(1): 这表示查询将返回一个计数&#xff0c;count(1)是一种常见的计数…

【database1】mysql:DDL/DML/DQL,外键约束/多表/子查询,事务/连接池

文章目录 1.mysql安装&#xff1a;存储&#xff1a;集合&#xff08;内存&#xff1a;临时&#xff09;&#xff0c;IO流&#xff08;硬盘&#xff1a;持久化&#xff09;1.1 服务端&#xff1a;双击mysql-installer-community-5.6.22.0.msi1.2 客户端&#xff1a;命令行输入my…

松下课堂 | 什么是EPS?通过马达来辅助转向操作的系统

EPS , 松下 EPS是一种通过马达来减轻和辅助驾驶员在转向操作时所需力量的设备。此外&#xff0c;通过采用EPS&#xff0c;可望提高燃效&#xff0c;降低车辆重量。。。 背景 EPS是一种通过马达来减轻和辅助驾驶员在转向操作时所需力量的设备。此外&#xff0c;通过采用EPS&…

重庆交通大学24计算机考研数据速览,专硕第二年招生,复试线321分!

重庆交通大学&#xff08;Chongqing Jiaotong University&#xff0c;CQJTU&#xff09;&#xff0c;是由重庆市人民政府和中华人民共和国交通运输部共建的一所交通特色、以工为主的多科性大学&#xff0c;入选“中西部高校基础能力建设工程”、“卓越工程师教育培养计划”、国…

【机器学习300问】128、简述什么Word2Vec?

一、一句话说明Word2Vec是什么&#xff1f; Word2Vec是一种常见的词嵌入技术。Word2Vec的目标是将每个词表示为一个向量&#xff0c;使得这些向量能够反映出词语之间的相似性和关联性。 word2vec算法通过预测中心词和上下文词的共现概率来学习词向量&#xff0c;能够捕捉词语之…

TypedDict 解析

TypedDict 解析 文章目录 TypedDict 解析1. 类型安全性2. 可读性3. 可维护性TypedDict 的解决方案没有 TypedDict 会发生什么&#xff1f;使用 TypedDict 的优势 TypedDict 应用场景1. 配置文件解析2. API 数据解析3. 数据库记录表示4. 表单数据验证5. 大型团队协作6. 静态类型…

正则表达式与文本处理器

正则表达式 基础正大表达式 查看特定字符 grep grep-n the test.txt grep-in the test.txt-n 显示行号 -i 不区分大小写 -v 反转查找 [] &#xff1a;中括号里可以写元素&#xff0c;内容符合任意元素&#xff0c;就会过滤出来 ^ :写在中括号里&#xff0c;代表取反。以^开头&…

图像编辑技术的新篇章:基于扩散模型的综述

在人工智能的浪潮中&#xff0c;图像编辑技术正经历着前所未有的变革。随着数字媒体、广告、娱乐和科学研究等领域对高质量图像编辑需求的不断增长&#xff0c;传统的图像编辑方法已逐渐无法满足日益复杂的视觉内容创作需求。尤其是在AI生成内容&#xff08;AIGC&#xff09;的…

富文本编辑器CKEditor

介绍 富文本编辑器不同于文本编辑器,它提供类似于 Microsoft Word 的编辑功能 在Django中,有可以现成的富文本三方模块django-ckeditor,具体安排方式: pip install django-ckeditor==6.5.1官网:Django CKEditor — Django CKEditor 6.7.0 documentation 使用方式 创建项…

pytest测试框架flaky插件重试失败用例

Pytest提供了丰富的插件来扩展其功能&#xff0c;本章介绍下插件flaky &#xff0c;用于在测试用例失败时自动重新运行这些测试用例。与前面文章介绍的插件pytest-rerunfailures功能有些类似&#xff0c;但是功能上不如pytest-rerunfailures插件丰富。 flaky官方并没有明确pyt…

华为od-C卷200分题目2 - 找城市

华为od-C卷200分题目2 - 找城市 题目描述 一个城市规划问题&#xff0c;一个地图有很多城市&#xff0c;两个城市之间只有一种路径&#xff0c;切断通往一 个城市i的所有路径之后&#xff0c;其他的城市形成了独立的城市群&#xff0c;这些城市群里最大的城 市数量&#xff0…

QML 列表,图片展示(一)

文章目录 1.QML 列表&#xff0c;图片展示效果图2.项目基本说明3.项目详解3.1界面显示部分3.2 网络部分 4.源代码5.flickr图片查询链接&#xff0c;后面我们将调整代码&#xff0c;获取更多图片 1.QML 列表&#xff0c;图片展示效果图 2.项目基本说明 该项目来自Qt示例程序 Ph…