Cover Flow布局

Cover Flow布局

Cover Flow布局的实现,可参见教程:

本文内容也是来源于此

实现过程

Cover Flow布局也是一种Flow布局,所以布局的类可直接继承自UICollectionViewFlowLayout

基本设置

1.设置scrollDirectionUICollectionViewScrollDirectionHorizontal,表示水平滚动
需要注意的是,垂直滚动和水平滚动,其行间距和item间距的不同:

这里写图片描述

2.设置minimumInteritemSpacing为一个合理的值,这样item就可以在一行显示,而不是多行显示

这里写图片描述

3.设置minimumLineSpacing为负值,这样item就叠加显示

这里写图片描述

自定义布局

自定义布局中最主要的是还是根据item的中心点距collection view中心的距离,进行3D变换

这里写图片描述

1.当某个item的中心距离visibleRect的中心点小于ACTIVE_DISTANCE(一个定义的常量)时,就需要进行3D变换,这是中间item的效果

a.只进行translate的效果
这里写图片描述

b.再添加上rotate后的效果
这里写图片描述

c.再添加上scale后的效果
这里写图片描述

2.对于距离visibleRect的中心点太大的item,主要添加2个变换

a.添加translate后的效果

这里写图片描述

b.再添加rotate后的效果

这里写图片描述

其主要代码如下:

- (void)setCellAttributes:(UICollectionViewLayoutAttributes *)attributes forVisibleRect:(CGRect)visibleRect
{
    // 对给定的布局attributes应用cover flow效果

    // 跳过supplementary views.
    if (attributes.representedElementKind) return;

    // 计算距离可见区域中心的距离
    CGFloat distanceFromVisibleRectToItem = CGRectGetMidX(visibleRect) - attributes.center.x;
    CGFloat normalizedDistance = distanceFromVisibleRectToItem / ACTIVE_DISTANCE;
    BOOL isLeft = distanceFromVisibleRectToItem > 0;
    CATransform3D transform = CATransform3DIdentity;


    if (fabsf(distanceFromVisibleRectToItem) < ACTIVE_DISTANCE)
    {

        transform = CATransform3DTranslate(CATransform3DIdentity, (isLeft? - FLOW_OFFSET : FLOW_OFFSET)*ABS(distanceFromVisibleRectToItem/TRANSLATE_DISTANCE), 0, (1 - fabsf(normalizedDistance)) * 40000 + (isLeft? 200 : 0));

        // 设置透视
        transform.m34 = -1/(4.6777 * self.itemSize.width);

        CGFloat zoom = 1 + ZOOM_FACTOR*(1 - ABS(normalizedDistance));
        transform = CATransform3DRotate(transform, (isLeft? 1 : -1) * fabsf(normalizedDistance) * 45 * M_PI / 180, 0, 1, 0);
        transform = CATransform3DScale(transform, zoom, zoom, 1);
        attributes.zIndex = 1;

    }
    else
    {
        transform.m34 = -1/(4.6777 * self.itemSize.width);
        transform = CATransform3DTranslate(transform, isLeft? -FLOW_OFFSET : FLOW_OFFSET, 0, 0);
        transform = CATransform3DRotate(transform, (isLeft? 1 : -1) * 45 * M_PI / 180, 0, 1, 0);
        attributes.zIndex = 0;

    }

    attributes.transform3D = transform;
}

还有一点就是,在滚动停止的时候,让某个item居中。
实现- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity方法即可

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    // 返回想要collection view停止的位置

    // 首先计算想要collection view停止的位置
    CGFloat offsetAdjustment = MAXFLOAT;
    CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0);
    // 使用center找到可视区域
    CGRect proposedRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);

    // 获取可视区域中cell的attribute
    NSArray* array = [self layoutAttributesForElementsInRect:proposedRect];

    // 遍历找到距离中心最近的cell
    for (UICollectionViewLayoutAttributes* layoutAttributes in array)
    {
        // 跳过supplementary views
        if (layoutAttributes.representedElementCategory != UICollectionElementCategoryCell)
            continue;

        // 找到最小值
        CGFloat itemHorizontalCenter = layoutAttributes.center.x;
        if (fabsf(itemHorizontalCenter - horizontalCenter) < fabsf(offsetAdjustment))
        {
            offsetAdjustment = itemHorizontalCenter - horizontalCenter;
        }
    }

    return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}

一些问题

1.item显示的时候锯齿化严重
在实例教程中,是通过设置光栅化来解决的,需要自定义布局属性类

2.collection view中的第一个item和最后一个item不能滚动到中间
可设置collection view的section inset来解决

3.响应点击事件
上面提到的教程中,也给出了方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值