iOS/MacOS开发

有间隙卡片缩放/无缝CollectionViewBanner无限

2018-06-28  本文已影响79人  出神入化VV

Demo地址(支持cocopods)
博客传送门

为什么重复造轮子?

因为大多数banner都是无缝滚动,有卡片缩放效果的又没有PageControl,且PageControl样式不支持自定义,所以根据自己项目需求和UI需求,造了一个轮子,希望分享出来能对大家有帮助,好用的话点个星

gif介绍

原理分析

UICollectionView无限轮播,网上有很多demo是利用数组复制100份,甚至1000份,利用cell复用机制,达到"无限轮播"的效果.
这种方案太简单粗暴,当然很实用.我是用另一种方案做的

//允许更新位置, 这个如果不写,一个循环内卡片越来越小,最后等循环结束开始下个循环时,cell重置大小
  - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)oldBounds
  {
      return YES;
  }
  - (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
  {
      NSArray* array = [super layoutAttributesForElementsInRect:rect];
      CGRect visibleRect;
      visibleRect.origin = self.collectionView.contentOffset;
      visibleRect.size = self.collectionView.bounds.size;
      [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
          UICollectionViewLayoutAttributes* attributes = (UICollectionViewLayoutAttributes *)obj;
          CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
          CGFloat normalizedDistance = ABS(distance/BannerOffsetWidth);
          CGFloat zoom = 1 - ZoomFactor*normalizedDistance;
          attributes.transform3D = CATransform3DMakeScale(1.0, zoom, 1.0);
          attributes.zIndex = 1;
      }];
      return array;
  }

继承UIPageControl,重写layoutSubviews方法,自己计算圆点之间间距,圆点尺寸,切圆角;如果喜欢的话,也可以做成自定义图片

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    self.userInteractionEnabled = NO;
    
    CGFloat allW = (self.subviews.count - 1)*(PageW+PageLine)+CurrentW;
    CGFloat originX = self.frame.size.width/2-allW/2;
    for (int i = 0; i < self.subviews.count; i++) {
        UIView *view = self.subviews[i];
        if (i == self.currentPage) {//当前page
            view.frame = CGRectMake(originX+ i*(PageW+PageLine), view.frame.origin.y, CurrentW, CurrentH);
        } else if (i > self.currentPage) {
                view.frame = CGRectMake(originX+ i * (PageW+PageLine)+(CurrentW-PageW), view.frame.origin.y, PageW, PageH);
        } else {
                view.frame = CGRectMake(originX+ i * (PageW+PageLine), view.frame.origin.y, PageW, PageH);
        }
        
        view.layer.cornerRadius = 1;
        view.layer.masksToBounds = YES;
    }
}

结语

上一篇 下一篇

猜你喜欢

热点阅读