滾動(dòng)放大縮小.gif
簡(jiǎn)介
效果:滾動(dòng)到中間的時(shí)候最大,距離中間越遠(yuǎn)越小.
思路:實(shí)現(xiàn)這樣的效果,我們首先要選對(duì)UI組件,這里我選擇使用UICollectionView
,而它的布局主要是依靠其flowLayout,所以我決定自定義FlowLayout實(shí)現(xiàn)該效果.
步驟
自定義WYCollectionViewFlowLayout
繼承自UICollectionViewFlowLayout
重寫3個(gè)布局方法
@interface WYCollectionViewFlowLayout : UICollectionViewFlowLayout
@end
@implementation WYCollectionViewFlowLayout
// 這個(gè)方法返回所有的布局所需對(duì)象,瀑布流也可以重寫這個(gè)方法實(shí)現(xiàn).
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
// 1.獲取cell對(duì)應(yīng)的attributes對(duì)象
NSArray *arrayAttrs = [super layoutAttributesForElementsInRect:rect];
// 2.計(jì)算整體的中心點(diǎn)的x值
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width * 0.5;
// 3.修改一下attributes對(duì)象
for (UICollectionViewLayoutAttributes *attr in arrayAttrs) {
// 3.1 計(jì)算每個(gè)cell的中心點(diǎn)距離
CGFloat distance = ABS(attr.center.x - centerX);
// 3.2 距離越大澳叉,縮放比越小,距離越小,縮放比越大
CGFloat factor = 0.003;
CGFloat scale = 1 / (1 + distance * factor);
attr.transform = CGAffineTransformMakeScale(scale, scale);
}
return arrayAttrs;
}
// 當(dāng)bounds發(fā)生改變的時(shí)候需要重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return true;
}
/// 滑動(dòng)停止
///
/// @param proposedContentOffset 當(dāng)手指滾動(dòng)完畢后装畅,自然情況下根據(jù)“慣性”,會(huì)停留的位置
/// @param velocity 速率,周率
///
/// @return 人為要讓它停留的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
// 1.計(jì)算中心點(diǎn)位置
CGFloat centerX = proposedContentOffset.x + self.collectionView.bounds.size.width * 0.5;
// 2.計(jì)算可視化區(qū)域
CGFloat visibleX = proposedContentOffset.x;
CGFloat visibleY = proposedContentOffset.y;
CGFloat visibleW = APP_WIDTH;
CGFloat visibleH = self.collectionView.bounds.size.height;
CGRect visibleRect = CGRectMake(visibleX, visibleY, visibleW, visibleH);
// 3.獲取可視區(qū)域的cell的attribute對(duì)象
NSArray *attrs = [self layoutAttributesForElementsInRect:visibleRect];
// 4.比較出最小的偏移
int min_idx = 0;
UICollectionViewLayoutAttributes *min_attr = attrs[min_idx];
// 5.循環(huán)比較出最小的
for (int i = 1; i< attrs.count; i++){
// 5.1min_attr和中心點(diǎn)的距離
CGFloat distance1 = ABS(min_attr.center.x - centerX);
// 5.2當(dāng)前循環(huán)的attr和中心點(diǎn)的距離
UICollectionViewLayoutAttributes *currentAttr = attrs[i];
CGFloat distance2 = ABS(currentAttr.center.x - centerX);
if (distance2 < distance1) {
min_idx = i;
min_attr = currentAttr;
}
}
// 6.計(jì)算出最小的偏移值
CGFloat offsetX = min_attr.center.x - centerX;
return CGPointMake(proposedContentOffset.x + offsetX, proposedContentOffset.y);
}
@end
然后在初始化UICollectionView
的時(shí)候,設(shè)置其流水布局collectionViewLayout
為我們自定義的WYCollectionViewFlowLayout
即可實(shí)現(xiàn)滾動(dòng)的放大縮小了.