#import "YHTestContentView.h"
#define CARDVIEWS 5 // 所有的卡片数量
@interface YHTestContentView ()<UIScrollViewDelegate>
@property (nonatomic, strong) UIScrollView *testView;
/** 保存可见的视图*/
@property (nonatomic, strong) NSMutableSet *visibleViews;
/** 保存可重用的视图*/
@property (nonatomic, strong) NSMutableSet *reusedViews;
@end
@implementation YHTestContentView
- (instancetype)init{
if (self = [super init]) {
[self initView];
}
return self;
}
- (void)initView{
UIScrollView *testView = [[UIScrollView alloc] init];
self.testView = testView;
testView.showsHorizontalScrollIndicator = NO;
testView.clipsToBounds = NO;
testView.pagingEnabled = YES;
testView.frame = CGRectMake(0, 0, 256.0, 143.0);
testView.delegate = self;
[self addSubview:testView];
// 刚开始进来时只需显示需要显示的卡片数量
NSInteger needShowCards = [UIScreen mainScreen].bounds.size.width / 270 + 1;
for (int i = 0; i<CARDVIEWS; i++) {
if (i < needShowCards) {
UIView *view = [[UIView alloc] init];
view.tag = i;
view.backgroundColor = [UIColor colorWithRed:arc4random_uniform(255.0)/255.0 green:arc4random_uniform(255.0)/255.0 blue:arc4random_uniform(255.0)/255.0 alpha:1.0];
[self.testView addSubview:view];
view.frame = CGRectMake(i*(256.0 + 14.0), 0, 256, 143.0);
[self.visibleViews addObject:view];
}
}
CGFloat offsetX = [UIScreen mainScreen].bounds.size.width - 256.0;
self.testView.contentSize = CGSizeMake(CARDVIEWS*(256.0 + 14.0) - offsetX, 143.0);
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
return self.testView;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
// 可视区域
CGRect visibleBounds = scrollView.bounds;
CGFloat minx = CGRectGetMinX(visibleBounds);
CGFloat maxX = CGRectGetMaxX(visibleBounds);
// CGFloat width = CGRectGetWidth(visibleBounds);
NSInteger firstIndex = (NSInteger)floorf(minx/270.0);
NSInteger lastIndex = (NSInteger)floorf(maxX/270.0);
// firstIndex--;
// 这里做++是考虑到这里实现分页的方式可能会让用户看到重用的过程,所以往后扩容
lastIndex++;
// 处理越界的情况
if (firstIndex < 0) {
firstIndex = 0;
}
if (lastIndex >= CARDVIEWS) {
lastIndex = CARDVIEWS - 1;
}
// 回收不再显示的view
NSInteger imageViewIndex = 0;
for (UIImageView *imageView in self.visibleViews) {
imageViewIndex = imageView.tag;
// 不在显示范围内,删除不在显示范围内的view
if (imageViewIndex < firstIndex || imageViewIndex > lastIndex) {
[self.reusedViews addObject:imageView];
[imageView removeFromSuperview];
}
}
// 把集合self.visibleViews中和self.reusedViews集合中相同的元素删除
[self.visibleViews minusSet:self.reusedViews];
// 是否需要显示新的视图
for (NSInteger index = firstIndex; index <= lastIndex; index++) {
// isShow表示index索引对应的view是否已经在界面上显示,因为此时self.visibleViews记录的都是已经在界面上显示的view
BOOL isShow = NO;
for (UIView *view in self.visibleViews) {
if (view.tag == index) {
isShow = YES;
}
}
if (!isShow) {
// isShow = NO,表示当前需要在界面上显示的view却没有显示时,这时候就要去显示
[self showViewAtIndex:index];
}
}
}
#pragma mark - 显示界面上显示的view ----
- (void)showViewAtIndex:(NSInteger)index {
// 先从缓存池取
UIView *view = [self.reusedViews anyObject];
if (view) {
[self.reusedViews removeObject:view];
} else {
// 如果不存在再创建
view = [[UIView alloc] init];
}
view.backgroundColor = [UIColor colorWithRed:arc4random_uniform(255.0)/255.0 green:arc4random_uniform(255.0)/255.0 blue:arc4random_uniform(255.0)/255.0 alpha:1.0];
CGRect viewFrame = CGRectMake(270 *index, 0, 256, 143.0);
view.tag = index;
view.frame = viewFrame;
[self.visibleViews addObject:view];
[self.testView addSubview:view];
}
#pragma mark - 界面上显示的所有视图 ---
- (NSMutableSet *)visibleViews {
if (_visibleViews == nil) {
_visibleViews = [[NSMutableSet alloc] init];
}
return _visibleViews;
}
#pragma mark - 重用池 ----
- (NSMutableSet *)reusedViews {
if (_reusedViews == nil) {
_reusedViews = [[NSMutableSet alloc] init];
}
return _reusedViews;
}
@end
UIScrollView实现重用性能优化
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 简介: UITableView我想大家都不陌生,他是UIKit一个重要组件。可以用来展示数据列表,或者灵活使用进行...
- 前言 在 Android开发中,性能优化策略十分重要本文主要讲解性能优化中的内存优化,希望你们会喜欢 目录 1. ...