CollectionView缩放水平卡片布局

实现效果

实现思路

从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,表示要滚动到下一个。所以在不分页的情况下,其实也是非常简单的。

时间: 2024-11-05 15:34:16

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

CollectionView旋转水平卡片布局

概述 UICollectionView真的好强大,今天我们来研究一下这种很常见的卡片动画效果是如何实现了.本篇不能太深入地讲解,因为笔者也是刚刚摸索出点眉目,但是并没有深刻地理解.如果在讲解过程中,出现不对的地方,请及时反馈. 效果图 重写API 1 2 3 4 5 6 7 8 9 10 11 12 // 我们必须重写此方法,指定布局大小 // 每次layout invalidated或者重新query布局信息时,会调用 - (void)prepareLayout; // 用于决定布局信息 //

GUI布局:边界布局、流式布局、网格布局、卡片布局

边界布局 package guiTest; //JFrame默认的是边界布局BorderLayout import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; public class BorderLayoutDemo { public static void main(String[] args) { JFrame f = new JFrame("边界布局BorderLayout&q

老白的JAVA课程16 卡片布局 javaBean

基于组件的开发 javaBean 组成部件 规范   1: 必须要有一个公共的构造方法,javaBean这个类也必须是公共的   2:javaBean中的属性都是私有的,每一个属性都必须提供符合命名规范的set和get方法   3:应该是可序列化的,但是并不是必须的 类型:  1:简单属性javabean  set和get足够简单  2:绑定属性JavaBean  属性复杂,需要绑定其他属性  3:约束属性JavaBean  set和get方法有约束 cardlayout.show(父容器,按钮

卡片布局页面跳转运用

例:我有一个ATM机界面,用的是卡片布局,现在我在查询功能页面,如果点击退出应该回到选择页面. import java.awt.*; import javax.swing.*; public class ChaXun { private ATMButton tuibtn; private Container contentp; public ChaXun(final ATMFrame frame){   //传入ATM整个大页面,想用它里面的什么就用什么 this.getContentP().s

卡片布局管理器(CardLayout)

1.作用: 卡片布局管理器是管理器的一种,卡片布局能够让多个组件共享同一个显示空间,共享空间的组件之间的关系就像一叠牌,组件叠在一起,初始时显示该空间中第一个添加的组件,通过CardLayout类提供的方法可以切换该空间中显示的组件. 2.CardLayout的常用构造方法: void   first(Container    parent)               翻转到指定容器的第一张卡片 void   next(Container   parent)               翻转到

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

对于选项卡这个概念大家可能不会陌生,就是在一个窗口中可以切换显示多页不同的内容,但同一时间只能是其中的某一页可见的,这样的一个个的页面就是选项卡. CardLayout就是类似的这样一个布局管理器,它能够让多个组件共享同一个显示空间,共享空间的组件之间的关系就像重叠在一起的一幅扑克牌,组件重叠在一起,初始时显示该空间中第一个组件,通过CardLayout类提供的方法可以切换该空间中显示的组件. 下面我们来看一个例子,实现CardLayout布局管理器的使用. 创建一个使用CardLayout布局

Java图形化界面设计——布局管理器之CardLayout(卡片布局)

卡片布局能够让多个组件共享同一个显示空间,共享空间的组件之间的关系就像一叠牌,组件叠在一起,初始时显示该空间中第一个添加的组件,通过CardLayout类提供的方法可以切换该空间中显示的组件. 1.  CardLayout类的常用构造函数及方法 2.  使用CardLayout类提供的方法可以切换显示该空间中的组件 方法一步骤: (1)      定义使用卡片布局的容器 例如:Panel cardPanel=new Panel(); (2)      定义卡片对象:CardLayout 布局对象

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

摘自 http://blog.csdn.net/liujun13579/article/details/7773945 三十二.Java图形化界面设计--布局管理器之CardLayout(卡片布局) 卡片布局能够让多个组件共享同一个显示空间,共享空间的组件之间的关系就像一叠牌,组件叠在一起,初始时显示该空间中第一个添加的组件,通过CardLayout类提供的方法可以切换该空间中显示的组件. 1.  CardLayout类的常用构造函数及方法 2.  使用CardLayout类提供的方法可以切换显

卡片布局管理器

本例因为要制作卡片布局管理器,所以首先要构造框架窗体.先通过函数this.setLayout(new BorderLayout())设置Frame的布局管理器为BorderLayout:再两次实例化Panel类得到两个对象pnlCommandArea和pnlDisplayArea:然后通过函数this.add( pnlCommandArea, BorderLayout.NORTH和函数this.add( pnlDisplayArea, BorderLayout.CENTER) 将两Panel对象