UIScrollView实现重用机制(类似多列tableview)
来源:互联网 发布:淘宝sc面膜是正品吗 编辑:程序博客网 时间:2024/05/22 03:32
要显示多列数据,在ios6之前可以通过自定义cell来实现,在ios6之后则可以使用UICollectionView。当然也有一种办法就是直接使用UIScrollView。不过UIScrollView并不像UITableview一样有重用机制,如果不经处理就加载多条数据,就会大量占用内存,程序越来越卡。本文的主题就是为UIScrollView实现重用机制,避免内存浪费。
总体的思路比较简单,就是在移动UIScrollView时判断其子视图在不在屏幕上,不在的话就将其移动。
下面直接上代码
@interface WLViewController : UIViewController<UIScrollViewDelegate>{ NSInteger cellViewHeight; NSInteger cellViewWide; NSInteger countOfRow; //一行的view个数 NSInteger queueCount; //队列里元素的个数 NSInteger dataIndex; NSInteger maxRow; NSInteger queueIndex; NSInteger preIndex; NSInteger maxindex;}-(void)loadDataOfCell:(UIView *) cell;-(void) cellHasBeensSlected:(NSInteger)inedx;-(void)writeCell:(UIView *)cell;-(void)readCell:(UIView *)cell withIndex:(NSInteger)index;
@interface WLViewController ()@property (nonatomic,strong) NSMutableArray *dataSure; //用来存放数据,应该是存做文件,为了简单,就先放在数组里@property (nonatomic,strong) NSMutableArray *viewQueue; //队列,通过更改队列里视图的矩形位置来实现滚动@property (nonatomic,strong) UIScrollView *mainView;@end@implementation WLViewController-(id)init{ return [self initWithCountOfRow:4];}-(id)initWithCountOfRow:(NSInteger)count{ self = [super init]; if(self) { countOfRow =count; cellViewHeight = cellViewWide = 320 / countOfRow; queueCount = countOfRow * 800 / cellViewHeight; queueCount -= countOfRow % 2 == 0 ? 0 : countOfRow / 2; self.dataSure = [[NSMutableArray alloc] init]; } return self;}- (void)viewDidLoad{ [super viewDidLoad]; self.viewQueue = [[NSMutableArray alloc] init]; self.mainView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.mainView.contentSize = CGSizeMake(320, 800); self.mainView.delegate = self; [self.view addSubview:self.mainView]; for(int i = 0; i < queueCount; i++) { CGRect rect = CGRectMake(i % countOfRow * cellViewWide, i / countOfRow * cellViewHeight, cellViewWide, cellViewHeight); AlbumView *album = [[AlbumView alloc] initWithFrame:rect]; [self.mainView addSubview:album]; [self.viewQueue addObject:album]; [self loadDataOfCell:album]; dataIndex++; } maxRow = 0; queueIndex = 0; }- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ //防止开始就向上滑 if(scrollView.contentOffset.y <= 0) return; int p = (int)scrollView.contentOffset.y / cellViewHeight; if(p >= maxRow) { //增加MAINVIEW的长度 [self addRows:p / 2 + 1]; maxRow = (self.mainView.contentSize.height - cellViewHeight * queueCount / countOfRow) / cellViewHeight; } if(p > preIndex) { [self pullDown:p-preIndex]; } else if (p < preIndex) { [self pullUp:preIndex - p]; } preIndex = p; //记录前一位置 if(dataIndex >= maxindex) maxindex = dataIndex;}-(void)addRows:(NSInteger)counts{ CGSize size = self.mainView.contentSize; size.height += cellViewHeight * counts; self.mainView.contentSize = size;}-(void)pullDown:(NSInteger)count{ for(int i = 0; i < countOfRow * count; i++) { AlbumView *album = [self.viewQueue objectAtIndex:queueIndex]; album.frame = CGRectMake(dataIndex % countOfRow * cellViewWide, dataIndex / countOfRow * cellViewHeight, cellViewWide, cellViewHeight); //如果没加载数据,就加载数据,如果已经加载过(向上滑动后又滑下),因为已经加载过一次,所以就直接读取 if(dataIndex >= maxindex) [self loadDataOfCell:album]; else [self readCell:album withIndex:dataIndex]; dataIndex++; //变更换队列的索引,指向下一个将要使用的视图 queueIndex = queueIndex + 1 == queueCount ? 0: queueIndex + 1; }}-(void)pullUp:(NSInteger)count{ for(int i = 0; i < countOfRow * count; i++) { dataIndex--; queueIndex = queueIndex == 0 ? queueCount - 1: queueIndex - 1; AlbumView *album = [self.viewQueue objectAtIndex:queueIndex]; album.frame = CGRectMake(dataIndex % countOfRow * cellViewWide, (dataIndex / countOfRow - queueCount / countOfRow ) * cellViewHeight, cellViewWide, cellViewWide); //向上滑动只需要读取之前加载的视图 [self readCell:album withIndex:dataIndex - queueCount]; }}-(void)loadDataOfCell:(UIView *)cell{ //获取数据源,如果从文件获取,则需要判断是否已经存在该文件。这里只是简化的写法。 [(AlbumView *)cell dosome]; ((AlbumView *)cell).i = dataIndex; [self writeCell:cell]; }-(void) cellHasBeensSlected:(NSInteger)inedx{ //钩子方法,在MAINVIEW的子视图被点击时调用 NSLog(@"------%d",inedx);}-(void)writeCell:(UIView *)cell{ //写方法,这里只简单的把视图的数据写入数组 AlbumView *album = [[AlbumView alloc] init]; album.backgroundColor = cell.backgroundColor; album.i = dataIndex; [self.dataSure addObject:album];}-(void)readCell:(UIView *)cell withIndex:(NSInteger)index{ /// /读方法,同上 AlbumView *subview = [self.dataSure objectAtIndex:index]; cell.backgroundColor = subview.backgroundColor; ((AlbumView *)cell).i = subview.i;}@end
为了实现钩子方法,这里选择写UIScrollView的分类的方式实现
@implementation UIScrollView (AlbumViewController)- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; if(![self.nextResponder.nextResponder isMemberOfClass:[WLViewController class]]) return; AlbumView *album = (AlbumView *)[self hitTest:[touch locationInView:self] withEvent:event]; [(WLViewController *)self.nextResponder.nextResponder cellHasBeensSlected:album.i]; }@end
最后是AlbumView类,这个类很随意。
@interface AlbumView : UIView@property (nonatomic) NSInteger i;-(void)dosome;@end
@implementation AlbumView-(void)dosome{ CGFloat r = (CGFloat)(arc4random() % 10) / 10.0; CGFloat g = (CGFloat)(arc4random() % 10) / 10.0; CGFloat b = (CGFloat)(arc4random() % 10) / 10.0; self.backgroundColor = [UIColor colorWithRed:r green:g blue:b alpha:1.0];}@end
一个简单的dome,只是简单的提供一个思路,如果投入使用的话还得进行一些细微的调整,例如,后台加载数据,以及等待数据加载时应该转菊花来增加用户体验等。
上传两张效果图
4 0
- UIScrollView实现重用机制(类似多列tableview)
- UISCrollView实现重用机制
- UIScrollView 实现 重用机制 dome
- tableVIew重用机制
- tableView的重用机制
- tableView的重用机制
- TableView的重用机制
- tableView的重用机制?
- TableView的重用机制
- tableview 重用机制
- # 多列类似Excel的TableView
- UIScrollView实现重用
- IOS tableView的重用机制
- IOS TableView Cell重用机制及TableView
- iOS TableView Cell重用机制及TableView
- UIScrollView的重用机制的理解
- UIScrollView的重用机制的理解
- UIScrollView的重用机制的理解
- oracle查询优化
- vimrc
- Samsung Galaxy S I9000 全系列解锁方法
- tq210 时钟和串口
- UBUNTU下搭建ANDROID开发环境遇到的三个问题及解决措施
- UIScrollView实现重用机制(类似多列tableview)
- android下xml序列化工具,生成xml文件方法
- List集合的一个常见错误
- OJ_1076 N的阶乘
- 如何设置已经创建的ComBoBox为CBS_DROPDOWNLIST样式
- 2014资料整理--NSArray用法(四)
- C#委托和多线程文章收藏
- 数据库系统的三级模式结构
- 中断处理的上下半部