Skip to content

Commit

Permalink
调整细节,修改bug
Browse files Browse the repository at this point in the history
  • Loading branch information
xiabob committed Mar 3, 2017
1 parent faa5bcb commit 0d1cad9
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 43 deletions.
5 changes: 3 additions & 2 deletions LazyScrollView/LazyScrollView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@
INFOPLIST_FILE = LazyScrollView/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.xiabob.LazyScrollView;
PRODUCT_BUNDLE_IDENTIFIER = xiabob.LazyScrollView;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
Expand All @@ -308,7 +308,7 @@
INFOPLIST_FILE = LazyScrollView/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.xiabob.LazyScrollView;
PRODUCT_BUNDLE_IDENTIFIER = xiabob.LazyScrollView;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
Expand All @@ -332,6 +332,7 @@
743FAFBD1E0BBA54008097E9 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
Expand Down
13 changes: 7 additions & 6 deletions LazyScrollView/LazyScrollView/Classes/LazyScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ typedef NS_ENUM(NSUInteger, LazyScrollViewDirection) {
@protocol LazyScrollViewDataSource <NSObject>

@required
// ScrollView一共展示多少个item
/// ScrollView一共展示多少个item
- (NSUInteger)numberOfItemInScrollView:(LazyScrollView *)scrollView;
// 要求根据index直接返回RectModel
/// 要求根据index直接返回RectModel
- (LSVRectModel *)scrollView:(LazyScrollView *)scrollView rectModelAtIndex:(NSUInteger)index;
// 返回下标所对应的view
/// 返回下标所对应的view
- (UIView *)scrollView:(LazyScrollView *)scrollView itemByLsvId:(NSString *)lsvId;

@end
Expand All @@ -35,7 +35,8 @@ typedef NS_ENUM(NSUInteger, LazyScrollViewDirection) {
@protocol LazyScrollViewDelegate<UIScrollViewDelegate>

@optional
- (void)scrollView:(LazyScrollView *)scrollView didClickItemAtIndex:(NSUInteger)index;
///点击了对应小标的cell
- (void)scrollView:(LazyScrollView *)scrollView didClickItemAtIndex:(NSUInteger)index withLsvId:(NSString *)lsvId;

@end

Expand Down Expand Up @@ -63,10 +64,10 @@ typedef NS_ENUM(NSUInteger, LazyScrollViewDirection) {
#pragma mark - LSVRectModel

@interface LSVRectModel : NSObject
// view转换后的绝对值rect
/// view转换后的绝对值rect
@property (nonatomic, assign) CGRect absRect;

// 业务下标,如果初始化时没有提供,LSVRectModel内部会自动生成
/// 业务下标,如果初始化时没有提供,LSVRectModel内部会自动生成
@property (nonatomic, copy) NSString *lsvId;

+ (instancetype)modelWithRect:(CGRect)rect;
Expand Down
56 changes: 40 additions & 16 deletions LazyScrollView/LazyScrollView/Classes/LazyScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ - (instancetype)init {

- (void)layoutSubviews {
[super layoutSubviews];
// TOOD: 此处算法待优化

NSMutableArray *newVisibleViews = [self getVisiableViewModels].mutableCopy;
NSMutableArray *newVisibleLsvIds = [newVisibleViews valueForKey:@"lsvId"];
NSMutableArray *removeViews = [NSMutableArray array];
Expand Down Expand Up @@ -115,8 +115,9 @@ - (void)layoutSubviews {
- (void)reloadData {
[self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.visibleViews removeAllObjects];
[self.reuseViewPool removeAllObjects];

[self updateAllDatas];
[self updateModelDatas];
}

- (void)enqueueReusableView:(UIView *)view {
Expand Down Expand Up @@ -158,11 +159,13 @@ - (void)registerClass:(Class)viewClass forViewReuseIdentifier:(NSString *)identi
#pragma mark - Utils

- (CGFloat)minEdgeOffset {
//for UIScrollView the bounds cahnge when scroll
CGFloat min = CGRectGetMinY(self.bounds);
return MAX(min - kBufferSize, 0);
}

- (CGFloat)maxEdgeOffset {
//for UIScrollView the bounds cahnge when scroll
CGFloat max = CGRectGetMaxY(self.bounds);
return MIN(max + kBufferSize, self.contentSize.height);
}
Expand All @@ -174,7 +177,7 @@ - (LSVRectModel *)findFirstAscendModelWithMinEdge:(CGFloat)minEdge {
NSInteger midIndex = (minIndex + maxIndex) / 2;
LSVRectModel *model = self.allAscendingRectModels[midIndex];

while (minIndex < maxIndex - 1) {
while (minIndex < midIndex && midIndex < maxIndex) {
if (CGRectGetMinY(model.absRect) > minEdge) {
maxIndex = midIndex;
}
Expand All @@ -185,9 +188,14 @@ - (LSVRectModel *)findFirstAscendModelWithMinEdge:(CGFloat)minEdge {
model = self.allAscendingRectModels[midIndex];
}

midIndex = MAX(midIndex - 1, 0);
//处理多个view的y值相同的情况
LSVRectModel *limitModel = model;
while (midIndex > 0 && CGRectGetMinY(model.absRect) == CGRectGetMinY(limitModel.absRect)) {
midIndex = MAX(midIndex - 1, 0);
model = self.allAscendingRectModels[midIndex];
}

return self.allAscendingRectModels[midIndex];
return model;
}

- (LSVRectModel *)findFirstDescendModelWithMaxEdge:(CGFloat)maxEdge {
Expand All @@ -197,7 +205,7 @@ - (LSVRectModel *)findFirstDescendModelWithMaxEdge:(CGFloat)maxEdge {
NSInteger midIndex = (minIndex + maxIndex) / 2;
LSVRectModel *model = self.allDescendingRectModels[midIndex];

while (minIndex < maxIndex - 1) {
while (minIndex < midIndex && midIndex < maxIndex) {
if (CGRectGetMaxY(model.absRect) < maxEdge) {
maxIndex = midIndex;
}
Expand All @@ -208,9 +216,14 @@ - (LSVRectModel *)findFirstDescendModelWithMaxEdge:(CGFloat)maxEdge {
model = self.allDescendingRectModels[midIndex];
}

midIndex = MAX(midIndex - 1, 0);
//处理多个view的y值相同的情况
LSVRectModel *limitModel = model;
while (midIndex > 0 && CGRectGetMaxY(model.absRect) == CGRectGetMaxY(limitModel.absRect)) {
midIndex = MAX(midIndex - 1, 0);
model = self.allDescendingRectModels[midIndex];
}

return self.allDescendingRectModels[midIndex];
return model;
}

- (NSArray *)getVisiableViewModels {
Expand All @@ -222,14 +235,12 @@ - (NSArray *)getVisiableViewModels {
LSVRectModel *firstDescendModel = [self findFirstDescendModelWithMaxEdge:[self maxEdgeOffset]];

NSInteger firstIndex = [self.allAscendingRectModels indexOfObject:firstAscendModel];
firstIndex = MAX(firstIndex-1, 0);
NSInteger lastIndex = [self.allAscendingRectModels indexOfObject:firstDescendModel];
lastIndex = MIN(lastIndex+1, self.allAscendingRectModels.count-1);

return [self.allAscendingRectModels subarrayWithRange:NSMakeRange(firstIndex, lastIndex-firstIndex+1)];
}

- (void)updateAllDatas {
- (void)updateModelDatas {
[self.allRectModels removeAllObjects];
self.allAscendingRectModels = nil;
self.allDescendingRectModels = nil;
Expand All @@ -250,17 +261,16 @@ - (void)handleTapAction:(UIGestureRecognizer *)gestureRecognizer {
CGPoint tapPoint = [gestureRecognizer locationInView:self];
for (LSVRectModel *model in visibleViews) {
if (CGRectContainsPoint(model.absRect, tapPoint)) {
if ([self.delegate respondsToSelector:@selector(scrollView:didClickItemAtIndex:)]) {
if ([self.delegate respondsToSelector:@selector(scrollView:didClickItemAtIndex:withLsvId:)]) {
NSInteger index = [self.allRectModels indexOfObject:model];
[self.delegate scrollView:self didClickItemAtIndex:index];
[self.delegate scrollView:self didClickItemAtIndex:index withLsvId:model.lsvId];
}

break;
}
}
}


#pragma mark - Setter

- (void)setDataSource:(id<LazyScrollViewDataSource>)dataSource {
Expand Down Expand Up @@ -292,7 +302,13 @@ - (NSMutableArray *)allAscendingRectModels {
//升序
_allAscendingRectModels = [[self.allRectModels
sortedArrayUsingComparator:^NSComparisonResult(LSVRectModel *obj1, LSVRectModel *obj2) {
return CGRectGetMinY(obj1.absRect) < CGRectGetMinY(obj2.absRect) ? NSOrderedAscending : NSOrderedDescending;}
CGFloat y1 = CGRectGetMaxY(obj1.absRect); CGFloat x1 = CGRectGetMinX(obj1.absRect);
CGFloat y2 = CGRectGetMaxY(obj2.absRect); CGFloat x2 = CGRectGetMinX(obj2.absRect);
if (y1 == y2) {
return x1 <= x2 ? NSOrderedAscending: NSOrderedDescending;
} else {
return y1 < y2 ? NSOrderedAscending : NSOrderedDescending;
} }
] mutableCopy];
}

Expand All @@ -304,7 +320,14 @@ - (NSMutableArray *)allDescendingRectModels {
//需要降序,而sortedArrayUsingComparator的结果是ascending order,所以block里面的结果是相反的。
_allDescendingRectModels = [[self.allRectModels
sortedArrayUsingComparator:^NSComparisonResult(LSVRectModel *obj1, LSVRectModel *obj2) {
return CGRectGetMaxY(obj1.absRect) < CGRectGetMaxY(obj2.absRect) ? NSOrderedDescending : NSOrderedAscending;}
CGFloat y1 = CGRectGetMaxY(obj1.absRect); CGFloat x1 = CGRectGetMinX(obj1.absRect);
CGFloat y2 = CGRectGetMaxY(obj2.absRect); CGFloat x2 = CGRectGetMinX(obj2.absRect);
if (y1 == y2) {
return x1 <= x2 ? NSOrderedDescending : NSOrderedAscending;
} else {
return y1 < y2 ? NSOrderedDescending : NSOrderedAscending;
}
}
] mutableCopy];
}

Expand Down Expand Up @@ -337,6 +360,7 @@ - (UITapGestureRecognizer *)tapGesture {
@end


#pragma mark - LSVRectModel

@implementation LSVRectModel

Expand Down
68 changes: 49 additions & 19 deletions LazyScrollView/LazyScrollView/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,55 @@ - (void)loadView {
[super loadView];

[self loadDatas];
[self setupUI];
[self configViews];
}

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}

- (void)setupUI {
- (void)loadDatas {

NSMutableArray *array = @[].mutableCopy;
NSMutableDictionary *dictionary = @{}.mutableCopy;

NSMutableArray *rectArray = [[NSMutableArray alloc] init];
//Create a single column layout with 5 elements;
for (int i = 0; i < 500 ; i++) {
[rectArray addObject:[NSValue valueWithCGRect:CGRectMake(10, i *80 + 2 , self.view.bounds.size.width-20, 80-2)]];
}
//Create a double column layout with 10 elements;
for (int i = 0; i < 1000 ; i++) {
[rectArray addObject:[NSValue valueWithCGRect:CGRectMake((i%2)*self.view.bounds.size.width/2 + 3, 41000 + i/2 *80 + 2 , self.view.bounds.size.width/2 -3, 80 - 2)]];
}
//Create a trible column layout with 15 elements;
for (int i = 0; i < 1500 ; i++) {
NSUInteger row = 5;
[rectArray addObject:[NSValue valueWithCGRect:CGRectMake((i%row)*self.view.bounds.size.width/row + 1, 82000 + i/row *80 + 2 , self.view.bounds.size.width/row -4, 80 - 2)]];
}

for (NSInteger index = 0; index < rectArray.count; ++ index) {
NSString *lsvId = [NSString stringWithFormat:@"%@/%@", @(index / 10), @(index % 10)];
LSVRectModel *model = [LSVRectModel modelWithRect:[(NSValue *)(rectArray[index]) CGRectValue] lsvId:lsvId];
[array addObject:model];
[dictionary setObject:lsvId forKey:lsvId];
}


// for (NSInteger index = 0; index < 5000; ++ index) {
// NSString *lsvId = [NSString stringWithFormat:@"%@/%@", @(index / 10), @(index % 10)];
// CGFloat width = ([UIScreen mainScreen].bounds.size.width - 30) / 2;
// LSVRectModel *model = [LSVRectModel modelWithRect:CGRectMake(10 + (index % 2) * (width+10), (index / 2) * (width+10), width, width) lsvId:lsvId];
// [array addObject:model];
// [dictionary setObject:lsvId forKey:lsvId];
// }
self.rectDatas = array;
self.viewsData = dictionary;

}

- (void)configViews {

self.view.backgroundColor = [UIColor whiteColor];

Expand All @@ -46,6 +86,8 @@ - (void)didReceiveMemoryWarning {
// Dispose of any resources that can be recreated.
}

#pragma mark - LazyScrollViewDataSource

- (NSUInteger)numberOfItemInScrollView:(LazyScrollView *)scrollView {
return self.rectDatas.count;
}
Expand Down Expand Up @@ -78,24 +120,12 @@ - (UIView *)scrollView:(LazyScrollView *)scrollView itemByLsvId:(NSString *)lsvI
return view;
}

- (void)scrollView:(LazyScrollView *)scrollView didClickItemAtIndex:(NSUInteger)index {
NSLog(@"didClickItemAtIndex:%@", @(index));
}
#pragma mark - LazyScrollViewDelegate

- (void)loadDatas {

NSMutableArray *array = @[].mutableCopy;
NSMutableDictionary *dictionary = @{}.mutableCopy;
for (NSInteger index = 0; index < 5000; ++ index) {
NSString *lsvId = [NSString stringWithFormat:@"%@/%@", @(index / 10), @(index % 10)];
CGFloat width = ([UIScreen mainScreen].bounds.size.width - 30) / 2;
LSVRectModel *model = [LSVRectModel modelWithRect:CGRectMake(10 + (index % 2) * (width+10), (index / 2) * (width+10), width, width) lsvId:lsvId];
[array addObject:model];
[dictionary setObject:lsvId forKey:lsvId];
}
self.rectDatas = array;
self.viewsData = dictionary;

- (void)scrollView:(LazyScrollView *)scrollView didClickItemAtIndex:(NSUInteger)index withLsvId:(NSString *)lsvId {
SingleView *view = (SingleView *)[self scrollView:scrollView itemByLsvId:lsvId];
NSLog(@"didClickItemAtIndex:%@ lsvid:%@ view data:%@", @(index), lsvId, view.data);
[scrollView reloadData];
}


Expand Down

0 comments on commit 0d1cad9

Please sign in to comment.