在iOS上实现瀑布流界面

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

时间: 2024-12-03 19:39:45

在iOS上实现瀑布流界面的相关文章

android-瀑布流 界面 实现问题

问题描述 瀑布流 界面 实现问题 如何 这个界面 有两个瀑布流 外面只能套一个scrollview实现 但是瀑布流的高度不能像listview gridview那样复写 有哪位同学 知道如何解决 解决方案 在iOS上实现瀑布流界面在iOS上实现瀑布流界面iOS 实现瀑布流界面 解决方案二: 用RecyclerView可以实现.参考:http://blog.csdn.net/lmj623565791/article/details/45059587

Android瀑布流照片墙实现,体验不规则排列的美感

传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在不知不觉中大家都已经对它 产生了审美疲劳.这个时候瀑布流布局的出现,就给人带来了耳目一新的感觉,这种布局虽然看上去貌似毫 无规律,但是却有一种说不上来的美感,以至于涌现出了大批的网站和应用纷纷使用这种新颖的布局来设计 界面. 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候是使 用的GridView来进行布局的,这种布局方式只适用于"墙"上的每张图片大小都相同的情况,如果图片的大 小

Android瀑布流照片墙实现 体验不规则排列的美感_Android

传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在不知不觉中大家都已经对它产生了审美疲劳.这个时候瀑布流布局的出现,就给人带来了耳目一新的感觉,这种布局虽然看上去貌似毫无规律,但是却有一种说不上来的美感,以至于涌现出了大批的网站和应用纷纷使用这种新颖的布局来设计界面. 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候是使用的GridView来进行布局的,这种布局方式只适用于"墙"上的每张图片大小都相同的情况,如果图片的大小参差不齐,

Pinterest采用瀑布流的方式网页设计

文章描述:浅谈个人在瀑布流网页的实现中遇到的问题和解决方法. 先上Demo 瀑布流排序 : http://cued.xunlei.com/demos/publ/demo1.html 瀑布流+无限拖 http://cued.xunlei.com/demos/publ/demo2.html 随着pinterest的走红,瀑布流式的布局被越来越多的网站所使用,这种布局确实有很多好处,图片列表页有很强大的视觉感染力,而且还提高了用户"发现好图"的效率.瀑布流的实现有很多种方式,之前淘宝UED有

浅谈瀑布流网页实现中遇到的问题和解决方法

  先上Demo 瀑布流排序 : http://cued.xunlei.com/demos/publ/demo1.html 瀑布流+无限拖 http://cued.xunlei.com/demos/publ/demo2.html 随着pinterest的走红,瀑布流式的布局被越来越多的网站所使用,这种布局确实有很多好处,图片列表页有很强大的视觉感染力,而且还提高了用 户"发现好图"的效率.瀑布流的实现有很多种方式,之前淘宝UED有篇文章详细的介绍过各种方式的优劣.今天我们主要讨论一下绝

Android App中实现相册瀑布流展示的实例分享_Android

传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在不知不觉中大家都已经对它产生了审美疲劳.这个时候瀑布流布局的出现,就给人带来了耳目一新的感觉,这种布局虽然看上去貌似毫无规律,但是却有一种说不上来的美感,以至于涌现出了大批的网站和应用纷纷使用这种新颖的布局来设计界面. 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候是使用的GridView来进行布局的,这种布局方式只适用于"墙"上的每张图片大小都相同的情况,如果图片的大小参差不齐,

Android App中实现相册瀑布流展示的实例分享

传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在不知不觉中大家都已经对它产生了审美疲劳.这个时候瀑布流布局的出现,就给人带来了耳目一新的感觉,这种布局虽然看上去貌似毫无规律,但是却有一种说不上来的美感,以至于涌现出了大批的网站和应用纷纷使用这种新颖的布局来设计界面. 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候是使用的GridView来进行布局的,这种布局方式只适用于"墙"上的每张图片大小都相同的情况,如果图片的大小参差不齐,

Android瀑布流照片墙实现 体验不规则排列的美感

传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在不知不觉中大家都已经对它产生了审美疲劳.这个时候瀑布流布局的出现,就给人带来了耳目一新的感觉,这种布局虽然看上去貌似毫无规律,但是却有一种说不上来的美感,以至于涌现出了大批的网站和应用纷纷使用这种新颖的布局来设计界面. 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候是使用的GridView来进行布局的,这种布局方式只适用于"墙"上的每张图片大小都相同的情况,如果图片的大小参差不齐,

iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流

上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewController(二) --详解CollectionView各种回调>.UICollectionView之所以强大,是因为其具有自定义功能,这一自定义就不得了啦,自由度非常大,定制的高,所以功能也是灰常强大的.本篇博客就不使用自带的流式布局了,我们要自定义一个瀑布流.自定义的瀑布流可以配置其参数: 每个Cell的边距