在iOS上实现瀑布流界面

openkk 12年前

前阵子需要做一个需求,在iPhone上实现瀑布流效果。

第一眼看到这个需求,我想到的两种解决方案分别是:

1. 使用多个UITableView,然后控制它们同时滚动;

 2. 使用一个UIScrollView,然后参考UITableView的实现自己做一个符合需求并且以后可以重用的控件。

 

我首先尝试了第一个方案,并且Google过控制多个UITableView同时滚动的代码,在StackOverflow里面找到一段蛮详细的代码了,不过在复杂的用户操作下,仍然会出现滚动不同步的情况。

最终,我放弃了这个方案。

 

而第二个方案的关键点就在于参考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 : %@\n", 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 : %@\n", 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 : %@\n", 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 : %@\n", cell);                    }                }            }        }  
主要思想就是,1. 找到一个需要展示的Cell;2. 以这个Cell开始,向前、向后推进,为需要展现出来的Cell分配;3. 遍历可见Cell,回收不可见的对象。

最后,把代码稍微做了抽离,弄了个小Demo,放到GitHub:https://github.com/siqin/WaterFlow

转自:http://blog.csdn.net/jasonblog/article/details/7588532