CollectionView垂直缩放卡片布局

概述

突然想起小美到家App中的一个列表效果,反正正好最近在研究collectonview,正在拿它个效果来练练手。今天教大家如何实现竖直滚动的列表缩放式效果,体验果然提高了不少。

实现效果

缘由

10个月前的事了,那时候在一个很小的创业公司里做美容O2O的,然后研究了很多同行的App,看着人家的效果却不知如何入手,只怪当初太菜。

利用周末研究了一下,果然还是实现出来了。哈哈,时隔这么久还是不能忘记这份“耻辱”啊。不过上周末可不只是实现了这种效果哦,还有好几种效果的。大家可以看文章末尾的推荐阅读。

实现思路

从效果图可以看到变化是,越是往中间滚动的item显示最大,越显眼。而越是往前面,或者越是后面的,反而显示越小,这样就形成了视觉差。

实现的思路就是通过重写在可见范围内的所有item的方法:

1

2

3

 

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect

 

通过这个API可以获取到原始属性,然后利用公式来计算缩放。

难点

如何计算缩放系数。这里实现的效果的公式如下:

1

2

3

 

CGFloat zoom = 1 + 0.15 * (1 - fabs(widthForScale));

 

其中,widthForScale是最难把握的系数。

如何计算widthForScale呢?方法是利用item的中心y与当前collectionview的contentOffset.y来计算:

1

2

3

4

 

CGFloat distance =  obj.center.y - fabs(offset) - self.itemSize.width;

CGFloat widthForScale = distance / self.itemSize.height;

 

其中,offset这么计算出来的:

1

2

3

4

5

6

7

 

CGRect visibleRect = CGRectZero;

visibleRect.origin = self.collectionView.contentOffset;

visibleRect.size = self.collectionView.frame.size;

  

CGFloat offset = CGRectGetMinY(visibleRect);

 

最大的难点是distance的计算,如何拿捏呢?这需要慢慢分析。

假设有三个item显示,那么第一个item的缩放要比第二个item(主显示的item)要小,然后第二个item的缩放要比第三个要大。

第二个item(主)比第一个多了一个item,而第三个又比第二个多了一个item,所以再减去一个item的宽就可以了。

核心代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

 

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {

  NSArray *superAttributes = [super layoutAttributesForElementsInRect:rect];

  NSArray *attributes = [[NSArray alloc] initWithArray:superAttributes copyItems:YES];

  

  CGRect visibleRect = CGRectZero;

  visibleRect.origin = self.collectionView.contentOffset;

  visibleRect.size = self.collectionView.frame.size;

  

  CGFloat offset = CGRectGetMinY(visibleRect);

  

  [attributes enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *obj, NSUInteger idx, BOOL * _Nonnull stop) {

    CGFloat distance =  obj.center.y - fabs(offset) - self.itemSize.width;

    CGFloat widthForScale = distance / self.itemSize.height;

    

      CGFloat zoom = 1 + 0.15 * (1 - fabs(widthForScale));

      obj.transform3D = CATransform3DMakeScale(zoom, 1.0, 1.0);

  }];

  return attributes;

}

 

系数0.15自由调整。

结尾

这里没有实现分页的特性,笔者还是尝试了的,不过因为一个item不是占满全屏,所以计算起来总是达不到笔者期望的效果。大家若能在笔者的基础上研究出来,请主动通知笔者,谢谢!

源代码

CollectionViewDemos

提示:本篇文章的demo对应于工程中的Demo4-CardLayout-vertical-scale分组。

推荐阅读

时间: 2024-12-08 21:55:51

CollectionView垂直缩放卡片布局的相关文章

CollectionView旋转水平卡片布局

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

CollectionView缩放水平卡片布局

概述 本篇一起来学习如何使用UICollectionView来实现水平滚动的缩放式卡片布局,就像Nice App中的卡片布局. 前一篇中讲了如何实现CollectionView旋转水平卡片布局,如果还没有阅读过,不防先看看再继续往下阅读. 实现效果 实现思路 从Demo效果图中,可以看出来,主要是缩放系数的计算.对于不同距离的cell,其缩放系数要变化,以便整体协调显示. 所以,我们必须重写-layoutAttributesForElementsInRect:方法来实现所有当前可见的cell的a

Android编程重写ViewGroup实现卡片布局的方法_Android

本文实例讲述了Android编程重写ViewGroup实现卡片布局的方法.分享给大家供大家参考,具体如下: 实现效果如图: 实现思路 1. 重写onMeasure(int widthMeasureSpec, int heightMeasureSpec)设置每个子View的大小 2. 重写onLayout(boolean changed, int l, int t, int r, int b) 设置每个子View的位置 第一步:新建FlowLayout继承ViewGroup package com

关于java卡片布局管理器

问题描述 下面是关于卡片布局管理器,虽然代码没问题,只是有些地方不是太懂,望高手指点,plCenter.add(newButton("One"),"1");plCenter.add(newButton("two"),"2");plCenter.add(newButton("three"),"3");plCenter.add(newButton("four"),&quo

这个卡片布局到底哪儿错了啊

问题描述 红色出我报错的地方,我不知道哪里出错了,还请大家多多指教啊!!!packageStudies;importjava.awt.*;importjava.awt.event.ActionListener;importjavax.swing.*;publicclassCardLayoutTsetextendsPanelimplementsActionListener{PanelcardPanel=newPanel();//创建一个Panel对象CardLayoutc=newCardLayou

Android编程重写ViewGroup实现卡片布局的方法

本文实例讲述了Android编程重写ViewGroup实现卡片布局的方法.分享给大家供大家参考,具体如下: 实现效果如图: 实现思路 1. 重写onMeasure(int widthMeasureSpec, int heightMeasureSpec)设置每个子View的大小 2. 重写onLayout(boolean changed, int l, int t, int r, int b) 设置每个子View的位置 第一步:新建FlowLayout继承ViewGroup package com

垂直三栏布局拥有相同高度的方法(转)

我们都了解拥有相同高度的布局是很麻烦的事,有很多相关资料提到过相关设计方法,所以在这我就不多做解释了. 最近在研究一个两个栏目的动态布局,每个栏目背景不同.我立刻想起了Dan Cederholm的Faux Columns,但我仍然需要一个动态布局的方法.我又看了完美布局的文章One True Layout,但是有很多bug,需要许多注释和程序.甚至考虑用JavaScrip来实现栏目始终保持同一高度,但是不行.绝望之余,几乎要用table布局,不,一定还有更好的方法.我想着一个问题"盒子外面是什么

垂直三栏布局拥有相同高度的方法

作者: Alan Pearce原文: Multi-Column Layouts Climb Out of the Box地址: http://alistapart.com/articles/multicolumnlayouts 我们都了解拥有相同高度的布局是很麻烦的事,有很多相关资料提到过相关设计方法,所以在这我就不多做解释了. 最近在研究一个两个栏目的动态布局,每个栏目背景不同.我立刻想起了Dan Cederholm的Faux Columns,但我仍然需要一个动态布局的方法.我又看了完美布局的

Android自定义View实现垂直时间轴布局

时间轴,顾名思义就是将发生的事件按照时间顺序罗列起来,给用户带来一种更加直观的体验.京东和淘宝的物流顺序就是一个时间轴,想必大家都不陌生,如下图: 分析 实现这个最常用的一个方法就是用ListView,我这里用继承LinearLayout的方式来实现.首先定义了一些自定义属性: attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable