首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

iOS开发之UIScrollView无限滚动

UIScrollView 的无限滚动主要应用在图片轮播器、欢迎界面等场景。首先需要说明的是,文本所讲的是一种"笨办法",但是好理解且容易实现,在图片不多的时候用它也无妨。它的原理是在要显示的图片前后各加一张图片即在第一张图片之前放最后一张图片,在最后一张图片之后放第一张图片,然后在滚动到边缘的时候,巧妙的过渡一下就可以"瞒天过海","以假乱真"的造成无限滚动的假象。网络上有很多只用三张或两张图片实现的方法,效率比这个方法高,但实现起来稍微麻烦一点,有兴趣的可以去深入研究。 实现步骤 1、根据需求准备几张图片,在网上找了5张图片,分别命名为 img_01,img_02,img_03,img_04,img_05 。 2、代码实现,主要分为:添加UIScrollView,添加显示图片,添加UIPageControl,然后监听UIScrollView的滚动,根据滚动的位置来设置UIPageControl,最重要的是对于滚动到两个边缘时要特殊处理一下,代码如下: #import "ViewController.h" //屏幕宽度 #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width //图片高度 #define IMG_HEIGHT 180 //要显示的图片总数 #define MAX_SIZE 7 #import "ViewController.h" @interface ViewController () <UIScrollViewDelegate> //滚动视图 @property (strong, nonatomic) UIScrollView *loopScrollView; //指示器 @property (strong, nonatomic) UIPageControl *pageIndicator; //要展示的图片数组 @property(strong, nonatomic) NSMutableArray *imgArray; @end @implementation ViewController //懒加载数组 -(NSMutableArray *)imgArray { if(_imgArray == nil) { _imgArray = [[NSMutableArray alloc]initWithCapacity:MAX_SIZE]; //在要展示的5张图片的前后各加一张图片,第一张前面加第五张,第五张后面加第一张 [_imgArray addObject:[UIImage imageNamed:@"img_05.jpg"]]; for (int i = 1; i< MAX_SIZE - 1; i++) { NSString *imgName = [[NSString alloc]initWithFormat:@"img_0%d.jpg", i]; [_imgArray addObject:[UIImage imageNamed:imgName]]; } [_imgArray addObject:[UIImage imageNamed:@"img_01.jpg"]]; } return _imgArray; } - (void)viewDidLoad { [super viewDidLoad]; [self setupScrollView]; [self setupPageControl]; } /** * 创建UIScrollView并设置其属性 */ -(void)setupScrollView { UIScrollView *sc = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 64, SCREEN_WIDTH, IMG_HEIGHT)]; //创建UIImageView并添加到UIScrollView中 for (int i = 0; i< MAX_SIZE; i++) { UIImageView *img = [[UIImageView alloc]initWithImage:[self.imgArray objectAtIndex:i]]; img.frame = CGRectMake(SCREEN_WIDTH * i, 0, SCREEN_WIDTH, IMG_HEIGHT); [sc addSubview:img]; } //设置UIScrollView的属性 sc.contentSize = CGSizeMake(SCREEN_WIDTH * self.imgArray.count, IMG_HEIGHT); sc.showsHorizontalScrollIndicator = NO; sc.pagingEnabled = YES; //刚开始应该滚动到第二张显示,因为第一张其实是最后一张图片 [sc setContentOffset:CGPointMake(SCREEN_WIDTH, 0) animated:NO]; //设置代理并添加到当前view中 sc.delegate = self; [self.view addSubview:sc]; self.loopScrollView = sc; } /** * 创建UIPageControl并设置其属性 */ -(void)setupPageControl { //注意frame,这样设置可以居中显示 UIPageControl *pc = [[UIPageControl alloc]initWithFrame:CGRectMake(self.view.center.x - 50, CGRectGetMaxY(self.loopScrollView.frame) - 25 , 100, 25)]; //设置UIPageControl的属性并添加到当前view中 pc.numberOfPages = MAX_SIZE - 2; pc.currentPage = 0; pc.pageIndicatorTintColor = [UIColor redColor]; [self.view addSubview:pc]; self.pageIndicator = pc; } //UIScrollView的代理方法,在该方法中改变UIPageControl并且处理边缘滚动 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { //获取当前UIScrollView的位置 CGPoint offset = [scrollView contentOffset]; //算出滚动到第几页 int currentPage = offset.x/SCREEN_WIDTH; //设置UIPageControl self.pageIndicator.currentPage = currentPage - 1; //对最后一张和第一张要进行特殊处理 //1、如果是第一张 if (currentPage == 0) { //下面两个方法任选其一都可以达到效果,但是注意动画一定要设置为NO,不然会有视觉会有辣眼睛的感觉 //方法1 [self.loopScrollView setContentOffset:CGPointMake(SCREEN_WIDTH * (MAX_SIZE-2), 0) animated:NO]; //方法2,该方法要求设置contentSize时,任一方向就算不滚动也不能为0,否则无效 //[self.loopScrollView scrollRectToVisible:CGRectMake(SCREEN_WIDTH * (MAX_SIZE-2), 0, SCREEN_WIDTH, IMG_HEIGHT) animated:NO]; self.pageIndicator.currentPage = MAX_SIZE - 2; } //2、如果是最后一张 else if(currentPage == MAX_SIZE - 1) { [self.loopScrollView setContentOffset:CGPointMake(SCREEN_WIDTH, 0) animated:NO]; //[self.loopScrollView scrollRectToVisible:CGRectMake(SCREEN_WIDTH, 0, SCREEN_WIDTH, IMG_HEIGHT) animated:NO]; self.pageIndicator.currentPage = 0; } } @end 实现效果 图片无限轮播.gif 写在后面的话 其实实现轮播现在最好的方案应该是使用UICollectionView,因为它是利用重用机制来实现的,性能会好很多,代码写起来类似。后面有机会的话奉献一下实现方案~~~

优秀的个人博客,低调大师

【iOS 开发】tableView updates 对比 reloadData

Paste_Image.png 如图有一个 TableView,每行显示这一行是第几行,现在我希望每按一次 update 按钮,就动态地在下方加两行。那么简单粗暴的做法是 ,更改数据源,然后刷新一下列表: // tableData = ["0", "1", "2", "3"] @IBAction func update(_ sender: AnyObject) { tableData.append("\(tableData.count)") tableData.append("\(tableData.count)") tableView.reloadData() } 用膝盖想也知道,这会使得前四行没有被改动的地方也被刷新一遍,带来了不必要的性能损耗。 好一点的做法是下面这样的: // tableData = ["0", "1", "2", "3"] @IBAction func update(_ sender: AnyObject) { tableData.append("\(tableData.count)") tableData.append("\(tableData.count)") tableView.beginUpdates() let indexPaths = [IndexPath(row: tableData.count-2, section: 0), IndexPath(row: tableData.count-1, section: 0)] tableView.insertRows(at: indexPaths, with: UITableViewRowAnimation.automatic) tableView.endUpdates() } 与上面相比,这样做使得 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 方法被少调用了四次。 这里 beginUpdates 和 endUpdates 方法的作用是,将这两条语句之间的对 tableView 的 insert/delete 操作聚合起来,然后同时更新 UI。鉴于我这里只进行了一次 insert 操作,把这两条语句去掉也没事,但是出于规范还是应该写上,因为假如习惯不写,下面这样的代码会运行时崩溃: @IBAction func update(_ sender: AnyObject) { tableData.append("\(tableData.count)") tableData.append("\(tableData.count)") // tableView.beginUpdates() tableView.insertRows(at: [IndexPath(row: tableData.count-2, section: 0)], with: UITableViewRowAnimation.automatic) tableView.insertRows(at: [IndexPath(row: tableData.count-1, section: 0)], with: UITableViewRowAnimation.automatic) // tableView.endUpdates() } 因为第一次 insert 之后,当前 row 的总数量在 UI 上试图 4 变成 5,然而数据源是 6,它会检查使用者对 tableView 的 UI 操作,最后是不是和 numberOfRows 方法获取的值相对应。 总结 numberOfRows 方法调用: 都只调用一次 numberOfRows 方法 cellForRow 方法调用次数: reloadData 会为当前显示的所有cell调用这个方法,updates 只会为新增的cell调用这个方法cellForRow 方法调用时间: reloadData 会在 numberOfRows 方法调用后的某一时间异步调用 cellForRow 方法,updates 会在 numberOfRows 方法调用后马上调用 cellForRow 方法 reloadData 方法缺陷: 带来额外的不必要开销,缺乏动画updates 方法缺陷:deleteRows 不会调用 cellForRow 方法,可能导致显示结果与数据源不一致;需要手动保证 insertRows、deleteRows 之后,row 的数量与 numberOfRows 的结果一致,否则会运行时崩溃 部分文章中没有写,总结提到了的部分放在完整 demo 里面了:demo Github 地址

优秀的个人博客,低调大师

hadoop开发库webhdfs使用介绍

Hadoop1.0版本已经提供了对Web方式访问的全面支持,包括读写和文件管理,用户可以使用curl模拟Http消息进行测试,下面是WebHDFS提供的操作列表功能清单: HTTP GET• OPEN (see FileSystem.open)• GETFILESTATUS (see FileSystem.getFileStatus)• LISTSTATUS (see FileSystem.listStatus)• GETCONTENTSUMMARY (see FileSystem.getContentSummary)• GETFILECHECKSUM (see FileSystem.getFileChecksum)• GETHOMEDIRECTORY (see FileSystem.getHomeDirectory)• GETDELEGATIONTOKEN (see FileSystem.getDelegationToken)• HTTP PUT• CREATE (see FileSystem.create)• MKDIRS (see FileSystem.mkdirs)• RENAME (see FileSystem.rename)• SETREPLICATION (see FileSystem.setReplication)• SETOWNER (see FileSystem.setOwner)• SETPERMISSION (see FileSystem.setPermission)• SETTIMES (see FileSystem.setTimes)• RENEWDELEGATIONTOKEN (see DistributedFileSystem.renewDelegationToken)• CANCELDELEGATIONTOKEN (see DistributedFileSystem.cancelDelegationToken)• HTTP POST• APPEND (see FileSystem.append) 这里需要特别注意的是hadoop配置参数中界定了是否支持身份认证,并设定了默认的用户名webuser,用户可以自行修改是否启用和更改默认的用户,如果不作处理,有时候会出现,用户权限不够,无法执行某些操作的问题。 作者:张子良 出处:http://www.cnblogs.com/hadoopdev 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册