在iOS上實現瀑布流界面

openkk 12年前發布 | 35K 次閱讀 IOS Android開發 移動開發

前陣子需要做一個需求,在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

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!