实现效果

实现思路

从Demo效果图中,可以看出来,主要是缩放系数的计算。对于不同距离的cell,其缩放系数要变化,以便整体协调显示。

所以,我们必须重写-layoutAttributesForElementsInRect:方法来实现所有当前可见的cell的attributes。

计算比例,通过获取当前偏移rect的最小坐标x,再与atribute的中心x相减,再除以高度,就是高度的缩放倍数scaleForDistance。

 

最后,通过一个公式来计算缩放的Y系数。公式为:

 
1
2
3
 
scale = 1 + scaleFactor * (1 - fabs(scaleForDistance))
 

scaleFactor因子可以自由调整,值越大,显示就越大。

核心代码

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
#pragma mark - Override
- (void)prepareLayout {
  self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  self.minimumLineSpacing = 20;
  //  self.minimumInteritemSpacing = 20;
  self.sectionInset = UIEdgeInsetsMake(0, 30, 0, 30);
  self.itemSize = CGSizeMake(self.collectionView.frame.size.width - 60,
                             self.collectionView.frame.size.height - 180);
  [super prepareLayout];
}
 
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
  return YES;
}
 
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
  NSArray *superAttributes = [super layoutAttributesForElementsInRect:rect];
  NSArray *attributes = [[NSArray alloc] initWithArray:superAttributes copyItems:YES];
  
  CGRect visibleRect = CGRectMake(self.collectionView.contentOffset.x,
                                  self.collectionView.contentOffset.y,
                                  self.collectionView.frame.size.width,
                                  self.collectionView.frame.size.height);
  CGFloat offset = CGRectGetMidX(visibleRect);
  
  [attributes enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *attribute, NSUInteger idx, BOOL * _Nonnull stop) {
    CGFloat distance = offset - attribute.center.x;
    // 越往中心移动,值越小,那么缩放就越小,从而显示就越大
    // 同样,超过中心后,越往左、右走,缩放就越大,显示就越小
    CGFloat scaleForDistance = distance / self.itemSize.height;
    // 0.2可调整,值越大,显示就越大
    CGFloat scaleForCell = 1 + 0.2 * (1 - fabs(scaleForDistance));
    
    // only scale y-axis
    attribute.transform3D = CATransform3DMakeScale(1, scaleForCell, 1);
    attribute.zIndex = 1;
  }];
  
  return attributes;
}
 

实现pagingEnabled的样式

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
  BOOL pagingEnabled = NO;
  if (pagingEnabled) {
    // 分页以1/3处
    if (proposedContentOffset.x > self.previousOffsetX + self.itemSize.width / 3.0) {
      self.previousOffsetX += self.collectionView.frame.size.width - self.minimumLineSpacing * 2;
    } else if (proposedContentOffset.x < self.previousOffsetX  - self.itemSize.width / 3.0) {
      self.previousOffsetX -= self.collectionView.frame.size.width - self.minimumLineSpacing * 2;
    }
    
    proposedContentOffset.x = self.previousOffsetX;
  } else {
    CGFloat x = proposedContentOffset.x / (self.itemSize.width + self.minimumLineSpacing);
    int base = (int)x;
    
    proposedContentOffset.x = base * (self.itemSize.width + self.minimumLineSpacing);
  }
  
  return proposedContentOffset;
}
 

这里是以1/3.0为分界,左、右的1/3作为分界线,超过才会切换过去!

感谢

感谢评论的朋友们的一句话,点醒了笔者。对于不分页的情况下,其实只要使用当前的偏移x除(itemSize.width + minimumLineSpacing)就得到一个倍数,然后四舍五入。比如,4.3取整得到4,那么就是没有超过一半,就要往回滚。而4.6取整得到5,表示要滚动到下一个。所以在不分页的情况下,其实也是非常简单的。

CollectionView缩放水平卡片布局的更多相关文章

  1. CollectionView旋转水平卡片布局

    概述 UICollectionView真的好强大,今天我们来研究一下这种很常见的卡片动画效果是如何实现了.本篇不能太深入地讲解,因为笔者也是刚刚摸索出点眉目,但是并没有深刻地理解.如果在讲解过程中,出 ...

  2. Java基础之创建窗口——使用卡片布局管理器(TryCardLayout)

    控制台程序. 卡片布局管理器会生成一叠组件——一个组件放在另一个组件的上面.添加到容器中的第一个组件在堆栈的顶部,因此是可见的,添加的最后一个组件在堆栈的底部.使用默认的构造函数CardLayout( ...

  3. 转:三十二、Java图形化界面设计——布局管理器之CardLayout(卡片布局)

    转:http://blog.csdn.net/liujun13579/article/details/7773945 卡片布局能够让多个组件共享同一个显示空间,共享空间的组件之间的关系就像一叠牌,组件 ...

  4. 三十二、Java图形化界面设计——布局管理器之CardLayout(卡片布局)

    摘自 http://blog.csdn.net/liujun13579/article/details/7773945 三十二.Java图形化界面设计--布局管理器之CardLayout(卡片布局) ...

  5. 布局管理器之CardLayout(卡片布局管理器)

    对于选项卡这个概念大家可能不会陌生,就是在一个窗口中可以切换显示多页不同的内容,但同一时间只能是其中的某一页可见的,这样的一个个的页面就是选项卡. CardLayout就是类似的这样一个布局管理器,它 ...

  6. 技术胖Flutter第三季-18布局CardWidget 卡片布局组件

    技术胖Flutter第三季-18布局CardWidget 卡片布局组件 博客地址: https://jspang.com/post/flutter3.html#toc-420 最外面是Card布局,里 ...

  7. 慕课网5-2编程练习:flex布局制作卡片布局案例

    慕课网5-2编程练习:flex布局制作卡片布局案例 小伙伴们,学习了卡片布局,接下来我们根据效果图,也写出一个卡片布局的页面吧! 效果图如下: 任务 1.主体内容的卡片一行只能显示两个. 2.卡片与卡 ...

  8. CollectionView垂直缩放卡片布局

    实现效果 实现思路 从效果图可以看到变化是,越是往中间滚动的item显示最大,越显眼.而越是往前面,或者越是后面的,反而显示越小,这样就形成了视觉差. 实现的思路就是通过重写在可见范围内的所有item ...

  9. java 图形化小工具Abstract Window Toolit ;布局管理器FlowLayout流式布局;BorderLayout边界布局;GridLayout网格布局;CardLayou重叠卡片布局;BoxLayout方框布局;绝对定位

    1.FlowLayout流式布局管理器: FlowLayout布局管理器中,组件像水流一样向某方向流动(排列),遇到障碍(边界)就折回,重头开始排列 .在默认情况下,FlowLayout局管理器从左向 ...

随机推荐

  1. html template & import link bug

    html template & import link bug html templates is OK https://caniuse.com/#search=html%20template ...

  2. POJ2455 Secret Milking Machine【二分,最大流】

    题目大意:N个点P条边,令存在T条从1到N的路径,求路径上的边权的最大值最小为多少 思路:做了好多二分+最大流的题了,思路很好出 二分出最大边权后建图,跑dinic 问题是....这题是卡常数的好题! ...

  3. hdu1059(背包dp二进制优化)

    Dividing Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  4. [转]SQL SERVER数据库还原的方法

    SQL SERVER数据库还原的方法 在SQL SERVER 2005下还原数据库 1.新建数据库A,右键还原数据库,此时目标数据库为A,选择备份 文件B_db_201311040200.BAK,还原 ...

  5. [NOIP2000] 提高组 洛谷P1022 计算器的改良

    题目背景 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生. ...

  6. No route info of this topic

    使用rocketmq时报错 com.alibaba.rocketmq.client.exception.MQClientException: No route info of this topic, ...

  7. python监控tomcat日记文件

    最近写了一个用python监控tomcat日记文件的功能 实现的功能: 监控日记文件中实时过来的记录,统计每分钟各个接口调用次数,统计结果插入oracle #!/usr/bin/python # -* ...

  8. 《TCP/IP详解卷1:协议》——第1章:概述(转载)

    1.引言 很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但TCP/IP协议族允许它们互相进行通信.TCP/IP起源于60年代末美国政府资助的一个分组交换网络研究项目,到90年代已发展 ...

  9. java学习——关于java课件上动手动脑问题简单的分析

    问题一:关于以下的代码为什么会产生错误的问题的简单分析. 第一个动手动脑提供了一下的代码,可以发现,在Foo的这个类中只定义了一个Foo(int)类型的构造函数,在之前的学习工程中,我们并没有接触到j ...

  10. 【TFS 2017 CI/CD系列 - 02】-- Build篇

    .创建Build 登录TFS,在现有的[Projects]中选择一个需要要创建Build的Project,点击[Build & Release]跳转页面 在新页面中选择[Builds]选项卡, ...