LazyScrollView 是一个高性能的 scrollView 重用布局框架, 实现了视图的重用和自动加载。
使用时候的核心代码:
// This protocol represents the data model object.
@class TMMuiLazyScrollView;
@protocol TMMuiLazyScrollViewDataSource <NSObject>
@required
- (NSUInteger)numberOfItemInScrollView:(nonnull TMMuiLazyScrollView *)scrollView;
- (nonnull TMMuiRectModel *)scrollView:(nonnull TMMuiLazyScrollView *)scrollView
rectModelAtIndex:(NSUInteger)index;
- (nullable UIView *)scrollView:(nonnull TMMuiLazyScrollView *)scrollView itemByMuiID:(nonnull NSString *)muiID;
@end
类似UITableView的用法,最大的区别就是在布局前计算出每个view的位置frame:
1、获取要展示的个数
2、获取每个view的数据model
3、创建每个视图view
这里的model继承TMMuiRectModel,那么TMMuiRectModel又是怎样的呢?
/**
* It is a view model that holding information of view. At least holding absoluteRect and muiID.
*/
@interface TMMuiRectModel: NSObject
// A rect that relative to the scroll view.
@property (nonatomic, assign) CGRect absoluteRect;
// A uniq string that identify a model.
@property (nonatomic, copy, nonnull) NSString *muiID;
@end
从这里可以看出,每个model必须赋值frame,所以这里需要在布局前计算出每个view的位置frame,还有一个参数muiID,它是View的唯一标识符。
对于创建的每个view,可以继承<TMMuiLazyScrollViewCellProtocol>,来监测view的生命周期
protocol TMMuiLazyScrollViewCellProtocol<NSObject>
@optional
// if call dequeueReusableItemWithIdentifier to get a reuseable view,the same as "prepareForReuse" in UITableViewCell
- (void)mui_prepareForReuse;
// When view enter the visible area of LazyScrollView ,call this method.
// First 'times' is 0
- (void)mui_didEnterWithTimes:(NSUInteger)times;
// When we need render the view, call this method.
// The difference between this method and 'mui_didEnterWithTimes' is there is a buffer area in LazyScrollView(RenderBufferWindow), first we will call 'mui_afterGetView'.
- (void)mui_afterGetView;
@end
//
// ViewController.m
// Demo
//
// Created by 胡梦驰 on 2017/8/2.
// Copyright © 2017年 胡梦驰. All rights reserved.
//
#import "ViewController.h"
#import "TMMuiLazyScrollView.h"
@interface LazyScrollViewCustomView : UIView<TMMuiLazyScrollViewCellProtocol>
@end
@implementation LazyScrollViewCustomView
//在即将被复用时调用,通常用于清空View内展示的数据。类似与UITableViewCell 的 prepareForReuse
- (void)mui_prepareForReuse{
NSLog(@"- Prepare For Reuse -");
}
//进入屏幕LazyScroll可视范围内时执行,times是进入可视范围的次数,从0开始。重置times可以调用LazyScrollView的resetViewEnterTimes重置times
- (void)mui_didEnterWithTimes:(NSUInteger)times{
NSLog(@"- Did Enter With Times -");
}
//LazyScroll获取到View后执行。也就是执行完- (UIView *)scrollView:(TMMuiLazyScrollView *)scrollView itemByMuiID:(NSString *)muiID方法获取到视图之后。
- (void)mui_afterGetView{
NSLog(@"- AfterGetView -");
}
@end
@interface ViewController ()<TMMuiLazyScrollViewDataSource>
@property (nonatomic, strong) NSMutableArray *rectArray;
@end
#define WIDTH self.view.frame.size.width
#define HEIGHT self.view.frame.size.height
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.rectArray = [NSMutableArray array];
CGFloat height = 0;
//一行只放一个view
for(int i = 0; i < 2; i++){
CGRect frame = CGRectMake(16, 10+i*60, WIDTH-32, 50);
[self.rectArray addObject:[NSValue valueWithCGRect:frame]];
}
height += 120;
//一行放两个
for(int i = 0; i < 4; i++){
CGRect frame = CGRectMake(16+i%2*((WIDTH-42)/2+10), height+10+i/2*60, (WIDTH-42)/2, 50);
[self.rectArray addObject:[NSValue valueWithCGRect:frame]];
}
height+= 120;
//一行放三个
for(int i = 0; i < 6; i++){
CGRect frame = CGRectMake(16+i%3*((WIDTH-52)/3+10), height+10+i/3*60, (WIDTH-52)/3, 50);
[self.rectArray addObject:[NSValue valueWithCGRect:frame]];
}
height+= 120;
//创建scrollView
TMMuiLazyScrollView *scrollView = [[TMMuiLazyScrollView alloc] init];
scrollView.frame = CGRectMake(0, 20, WIDTH, HEIGHT-20);
scrollView.dataSource = self;
[self.view addSubview:scrollView];
//对scrollview的content大小设置,并加载reloadData
scrollView.contentSize = CGSizeMake(WIDTH, height);
[scrollView reloadData];
}
#pragma mark -- DataSource/Delegate
- (NSUInteger)numberOfItemInScrollView:(TMMuiLazyScrollView *)scrollView{
return self.rectArray.count;
}
- (TMMuiRectModel*)scrollView:(TMMuiLazyScrollView *)scrollView rectModelAtIndex:(NSUInteger)index{
CGRect frame = [(NSValue*)self.rectArray[index] CGRectValue];
TMMuiRectModel *model = [[TMMuiRectModel alloc] init];
model.absoluteRect = frame;
model.muiID = [NSString stringWithFormat:@"%ld", index];
return model;
}
- (UIView*)scrollView:(TMMuiLazyScrollView *)scrollView itemByMuiID:(NSString *)muiID{
NSInteger index = muiID.integerValue;
CGRect frame = [(NSValue*)self.rectArray[index] CGRectValue];
static NSString *identify = @"hmc";
LazyScrollViewCustomView *view = (LazyScrollViewCustomView*)[scrollView dequeueReusableItemWithIdentifier:identify];
if(!view){
view = [[LazyScrollViewCustomView alloc] initWithFrame:frame reuseIdentifier:identify];
view.backgroundColor = [UIColor cyanColor];
}
view.frame = frame;
view.backgroundColor = [self randomColor];
//切记要把创建的view添加到scrollview中
[scrollView addSubview:view];
return view;
}
//随机颜色
- (UIColor *)randomColor{
CGFloat hue = ( arc4random() % 256 / 256.0 ); //0.0 to 1.0
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0,away from white
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; //0.5 to 1.0,away from black
return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1];
}
@end