iOSで滝の流れを実現
先日はiPhoneで滝の流れを実現するための需要があった.
このニーズを一目で見て、私が考えている2つのソリューションは、次のとおりです.
1.複数のUItableViewを使用し、同時にスクロールするように制御します.
2.UIscrollViewを使用し、UItableViewの実装を参照して、必要に応じて後で再利用できるコントロールを作成します.
私はまず最初の案を試みて、Googleは複数のUItable Viewを同時にスクロールするコードを制御しすぎて、StackOverflowの中で1段のとても詳しいコードを見つけましたが、複雑なユーザーの操作の下で、依然としてスクロールが同期していない情況が現れます.
結局、私はこの案を放棄した.
2つ目のシナリオのキーは、UItableView実装を参照するときにセルを再利用する方法です.
次に、私が実装した再利用コードを示します.
主な考えは、1.展示が必要なセルを見つけることです.2.このセルで始まり、前、後ろに進み、必要なセルに割り当てる.3.表示されているセルを巡り、表示されていないオブジェクトを回収します.
最後に、コードを少し外して、小さなDemoを作って、GitHubに置きました.https://github.com/siqin/WaterFlow
このニーズを一目で見て、私が考えている2つのソリューションは、次のとおりです.
1.複数のUItableViewを使用し、同時にスクロールするように制御します.
2.UIscrollViewを使用し、UItableViewの実装を参照して、必要に応じて後で再利用できるコントロールを作成します.
私はまず最初の案を試みて、Googleは複数のUItable Viewを同時にスクロールするコードを制御しすぎて、StackOverflowの中で1段のとても詳しいコードを見つけましたが、複雑なユーザーの操作の下で、依然としてスクロールが同期していない情況が現れます.
結局、私はこの案を放棄した.
2つ目のシナリオのキーは、UItableView実装を参照するときにセルを再利用する方法です.
次に、私が実装した再利用コードを示します.
- (void)onScroll
{
for (int i = 0; i < self.columns; ++i) {
NSUInteger basicVisibleRow = 0;
WaterFlowViewCell *cell = nil;
CGRect cellRect = CGRectZero;
NSMutableArray *singleRectArray = [self.cellRectArray objectAtIndex:i];
NSMutableArray *singleVisibleArray = [self.visibleCells objectAtIndex:i];
if (0 == [singleVisibleArray count]) {
// There is no visible cells in current column now, find one.
for (int j = 0; j < [singleRectArray count]; ++j) {
cellRect = [(NSValue *)[singleRectArray objectAtIndex:j] CGRectValue];
if (![self canRemoveCellForRect:cellRect]) {
WFIndexPath *indexPath = [WFIndexPath indexPathForRow:j inColumn:i];
basicVisibleRow = j;
cell = [self.waterFlowDataSource waterFlowView:self cellForRowAtIndexPath:indexPath]; // nil ?
cell.indexPath = indexPath;
cell.frame = cellRect;
if (!cell.superview) [self addSubview:cell];
NSLog(@"Cell Info : %@
", cell);
[singleVisibleArray insertObject:cell atIndex:0];
break;
}
}
} else {
cell = [singleVisibleArray objectAtIndex:0];
basicVisibleRow = cell.indexPath.row;
}
// Look back to load visible cells
for (int j = basicVisibleRow - 1; j >= 0; --j) {
cellRect = [(NSValue *)[singleRectArray objectAtIndex:j] CGRectValue];
if (![self canRemoveCellForRect:cellRect]) {
WFIndexPath *indexPath = [WFIndexPath indexPathForRow:j inColumn:i];
if ([self containVisibleCellForIndexPath:indexPath]) {
continue ;
}
cell = [self.waterFlowDataSource waterFlowView:self cellForRowAtIndexPath:indexPath]; // nil ?
cell.indexPath = indexPath;
cell.frame = cellRect;
if (!cell.superview) [self addSubview:cell];
NSLog(@"Cell Info : %@
", cell);
[singleVisibleArray insertObject:cell atIndex:0];
} else {
break;
}
}
// Look forward to load visible cells
for (int j = basicVisibleRow + 1; j < [singleRectArray count]; ++j) {
cellRect = [(NSValue *)[singleRectArray objectAtIndex:j] CGRectValue];
if (![self canRemoveCellForRect:cellRect]) {
WFIndexPath *indexPath = [WFIndexPath indexPathForRow:j inColumn:i];
if ([self containVisibleCellForIndexPath:indexPath]) {
continue ;
}
cell = [self.waterFlowDataSource waterFlowView:self cellForRowAtIndexPath:indexPath]; // nil ?
cell.indexPath = indexPath;
cell.frame = cellRect;
if (!cell.superview) [self addSubview:cell];
NSLog(@"Cell Info : %@
", cell);
[singleVisibleArray insertObject:cell atIndex:0];
} else {
break;
}
}
// Recycle invisible cells
for (int j = 0; j < [singleVisibleArray count]; ++j) {
cell = [singleVisibleArray objectAtIndex:j];
if ([self canRemoveCellForRect:cell.frame]) {
[cell removeFromSuperview];
[self addReusableCell:cell];
[singleVisibleArray removeObject:cell];
--j;
NSLog(@"Removable Cell Info : %@
", cell);
}
}
}
}
主な考えは、1.展示が必要なセルを見つけることです.2.このセルで始まり、前、後ろに進み、必要なセルに割り当てる.3.表示されているセルを巡り、表示されていないオブジェクトを回収します.
最後に、コードを少し外して、小さなDemoを作って、GitHubに置きました.https://github.com/siqin/WaterFlow