美文网首页
[iOS][Objective-C]:collectionVie

[iOS][Objective-C]:collectionVie

作者: DerrickQin | 来源:发表于2016-10-13 10:05 被阅读0次
    这是一个demo:左右滑动与上部分类标签栏的联动效果,同时可以点击将分类标签栏打开明细进行选择。

    效果:


    collectionView联动.gif

    首先在底层创建一个大的collectionView,嵌套于一个tabBar和navigationBar中。
    然后创建对应的cell作为整个页面的容器。
    <pre><code>DQCollectionViewController
    DQCollectionViewCell</code></pre>
    对应该collectionView的数据源方法,我们这边就先设置8个页面。也就是对应上方分类栏有8个标签。
    DQCollectionViewController的设置:
    <pre>

    • (void)loadView {
      [super loadView];
      //设置高斯模糊:关闭
      self.navigationController.navigationBar.translucent = NO;
      self.tabBarController.tabBar.translucent = NO;
      //设置颜色
      self.collectionView.backgroundColor = [UIColor blueColor];
      self.navigationController.navigationBar.barTintColor = [UIColor cyanColor];
      self.tabBarController.tabBar.barTintColor = [UIColor cyanColor];
      //分页效果
      self.collectionView.pagingEnabled = YES;

      self.title = @"Demo";
      }
      </pre>

    上部联动的分类的CollectionView和对应的cell设置
    <pre>
    //
    // CategroyBaseView.m
    // CategroyCollectionView
    //
    // Created by admin on 16/8/29.
    // Copyright © 2016年 Derrick_Qin. All rights reserved.
    //

    import "CategroyBaseView.h"

    import "CategroyCell.h"

    //下标高度

    define kIndicatorH 3

    //选项cell宽度

    define kItemSizeW 55

    @interface CategroyBaseView () <UICollectionViewDataSource,
    UICollectionViewDelegate>

    @property(nonatomic, assign) BOOL btnIsClicked;
    @property(nonatomic, weak) UIView *indictorView;
    @property(nonatomic, weak) UICollectionView *cateView;
    @property(nonatomic, strong) NSIndexPath *selectedIndexPath;

    @end

    static NSString *cateCellReuseId = @"cateCell";

    @implementation CategroyBaseView

    • (instancetype)initWithFrame:(CGRect)frame {

      self = [super initWithFrame:frame];

      if (self) {

      self.backgroundColor = [UIColor whiteColor];

      [self setupBaseView:frame];

      [self setupButton:frame];

      [self setupCollectionView:frame];

      [self setupIndictor:frame];
      }

      return self;
      }

    /**

    • 添加底层View
    • @param frame
      */
    • (void)setupBaseView:(CGRect)frame {

      UIView *baseView = [[UIView alloc]
      initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];

      UILabel *textLabel = [[UILabel alloc]
      initWithFrame:CGRectMake(25, frame.size.height * 0.5 - 12.5, 120, 25)];

      textLabel.text = @"All Categroies";

      textLabel.font = [UIFont systemFontOfSize:13];

      textLabel.textColor = [UIColor darkGrayColor];

      [baseView addSubview:textLabel];

      baseView.backgroundColor =
      [UIColor colorWithRed:0.9444 green:0.9444 blue:0.9444 alpha:1.0];

      [self addSubview:baseView];
      }
      /**

    • 添加下拉按钮
    • @param frame
      */
    • (void)setupButton:(CGRect)frame {

      UIButton *changeBtn = [[UIButton alloc]
      initWithFrame:CGRectMake(frame.size.width - frame.size.height, 0,
      frame.size.height, frame.size.height)];

      UIImage *image = [UIImage imageNamed:@"explore_board_indicator"];

      UIImageView *btnImageView = [[UIImageView alloc] initWithImage:image];

      btnImageView.frame = CGRectMake(0, 0, changeBtn.bounds.size.width * 0.25,
      changeBtn.bounds.size.height * 0.25);

      btnImageView.center = CGPointMake(changeBtn.bounds.size.width * 0.5,
      changeBtn.bounds.size.height * 0.5);

      btnImageView.contentMode = UIViewContentModeScaleAspectFit;

      [changeBtn setBackgroundColor:[UIColor whiteColor]];

      _changeButton = changeBtn;

      [changeBtn addSubview:btnImageView];
      //添加点击触发事件
      [changeBtn addTarget:self
      action:@selector(changeBtnClick:)
      forControlEvents:UIControlEventTouchUpInside];

      [self addSubview:changeBtn];
      }

    /**

    • 添加collectionView
    • @param frame
      */
    • (void)setupCollectionView:(CGRect)frame {

      UICollectionViewFlowLayout *flowLayout =
      [[UICollectionViewFlowLayout alloc] init];

      flowLayout.itemSize = CGSizeMake(kItemSizeW, frame.size.height - kIndicatorH);

      flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);

      flowLayout.minimumLineSpacing = 0;

      flowLayout.minimumInteritemSpacing = 0;

      flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

      UICollectionView *cateView = [[UICollectionView alloc]
      initWithFrame:CGRectMake(0, 0,
      frame.size.width - frame.size.height,
      frame.size.height)
      collectionViewLayout:flowLayout];

      cateView.backgroundColor = [UIColor whiteColor];

      cateView.showsVerticalScrollIndicator = NO;

      cateView.showsHorizontalScrollIndicator = NO;

      cateView.bounces = NO;

      cateView.dataSource = self;

      cateView.delegate = self;

      _cateView = cateView;

      [self addSubview:cateView];

      [cateView registerClass:[CategroyCell class]
      forCellWithReuseIdentifier:cateCellReuseId];
      }

    • (void)setupIndictor:(CGRect)frame {

      UIView *indictorView = [[UIView alloc]
      initWithFrame:CGRectMake(0, frame.size.height - kIndicatorH, kItemSizeW,
      kIndicatorH)];

      indictorView.backgroundColor =
      [UIColor colorWithRed:1.0 green:0.0786 blue:0.2518 alpha:1.0];

      _indictorView = indictorView;

      [_cateView addSubview:indictorView];
      }

    /**

    • 按钮触发事件
    • @param changeBtn
      */
    • (void)changeBtnClick:(UIButton *)changeBtn {
      //记录按钮状态
      _btnIsClicked = !_btnIsClicked;

      UIImageView *imageView = _changeButton.subviews.lastObject;
      //旋转
      imageView.transform = _btnIsClicked ? CGAffineTransformMakeRotation(M_PI)
      : CGAffineTransformMakeRotation(0);

      if (_btnIsClicked) {

      _cateView.hidden = YES;

      [_changeButton setBackgroundColor:[UIColor colorWithRed:0.9444
      green:0.9444
      blue:0.9444
      alpha:1.0]];

      } else {
      [_changeButton setBackgroundColor:[UIColor whiteColor]];

      _cateView.hidden = NO;
      }

      if (_changeBtnClick) {

      _changeBtnClick(_changeButton, _btnIsClicked, _selectedIndexPath);
      }
      }

    • (NSInteger)numberOfSectionsInCollectionView:
      (UICollectionView *)collectionView {

      return 1;
      }

    • (NSInteger)collectionView:(UICollectionView *)collectionView
      numberOfItemsInSection:(NSInteger)section {

      return self.categroyArray.count;
      }

    • (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
      cellForItemAtIndexPath:(NSIndexPath *)indexPath {

      CategroyCell *cell =
      [collectionView dequeueReusableCellWithReuseIdentifier:cateCellReuseId
      forIndexPath:indexPath];

      NSString *title = self.categroyArray[indexPath.item];

      cell.title = title;

      if (indexPath.item == _selectedIndexPath.item) {

      cell.isSelected = YES;

      } else {
      cell.isSelected = NO;
      }

      return cell;
      }

    • (void)collectionView:(UICollectionView *)collectionView
      didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

      CategroyCell *selectedCell = (CategroyCell *)[collectionView
      cellForItemAtIndexPath:_selectedIndexPath];

      selectedCell.isSelected = NO;

      CategroyCell *cell =
      (CategroyCell *)[collectionView cellForItemAtIndexPath:indexPath];

      cell.isSelected = YES;

      _selectedIndexPath = indexPath;

      [UIView animateWithDuration:0.2
      animations:^{

                     CGRect currentRect = _indictorView.frame;
      
                     currentRect.origin.x = kItemSizeW * indexPath.item;
      
                     _indictorView.frame = currentRect;
                   }];
      

      if (_indexChange) {

      _indexChange(indexPath.item);
      }

      [_cateView
      scrollToItemAtIndexPath:indexPath
      atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
      animated:YES];
      }

    • (void)selectAtIndex:(NSInteger)index {

      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];

      [self collectionView:_cateView didSelectItemAtIndexPath:indexPath];
      }

    @end
    </pre>
    <pre>
    //
    // CategroyCell.m
    // CategroyCollectionView
    //
    // Created by admin on 16/8/29.
    // Copyright © 2016年 Derrick_Qin. All rights reserved.
    //

    import "CategroyCell.h"

    @interface CategroyCell ()
    @property(nonatomic, weak) UILabel *textLabel;
    @end

    @implementation CategroyCell

    • (instancetype)initWithFrame:(CGRect)frame {

      self = [super initWithFrame:frame];

      if (self) {

      UILabel *textLabel =
      [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 60, 25)];

      textLabel.textAlignment = NSTextAlignmentCenter;

      textLabel.center =
      CGPointMake(frame.size.width * 0.5, frame.size.height * 0.5);

      _textLabel = textLabel;

      [self.contentView addSubview:textLabel];
      }

      return self;
      }

    • (void)setTitle:(NSString *)title {

      _title = title;

      _textLabel.text = title;
      }

    @end
    </pre>
    实现上下联动的关键点:

    1. 上方分类栏点击,下方跟随滑动
      在collectionViewdidSelectItemAtIndexPath中实现点击方法:
      通过indexpath获取cell,底下红色条做动画,做block回调,然后使用scrollToItemAtIndexPath:atScrollPosition: 方法做分类栏的滑动跳转
      <pre>
    • (void)collectionView:(UICollectionView *)collectionView
      didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

      CategroyCell *selectedCell = (CategroyCell *)[collectionView
      cellForItemAtIndexPath:_selectedIndexPath];

      selectedCell.isSelected = NO;

      CategroyCell *cell =
      (CategroyCell *)[collectionView cellForItemAtIndexPath:indexPath];

      cell.isSelected = YES;

      _selectedIndexPath = indexPath;

      [UIView animateWithDuration:0.2
      animations:^{

                     CGRect currentRect = _indictorView.frame;
      
                     currentRect.origin.x = kItemSizeW * indexPath.item;
      
                     _indictorView.frame = currentRect;
                   }];
      

      if (_indexChange) {

      _indexChange(indexPath.item);
      }

      [_cateView
      scrollToItemAtIndexPath:indexPath
      atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
      animated:YES];
      }
      </pre>

    在DQCollectionViewController中添加block回调的实现,同样是scrollView的滑动方法:
    <pre>
    cateView.indexChange = ^(NSInteger itemIndex) {

    NSIndexPath *indexPath =
        [NSIndexPath indexPathForItem:itemIndex inSection:0];
    
    //记得动画效果去掉
    [self.collectionView
        scrollToItemAtIndexPath:indexPath
               atScrollPosition:UICollectionViewScrollPositionLeft
                       animated:NO];
    

    };
    </pre>

    1. 下方collectionView滑动同时联动上方的分类栏联动:
      这个相对比较简单,正向调用。重点是collectionView中的
    • (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 方法的实现,
      在滑动松手结束至停止时,带动上方做联动:

    <pre>

    • (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

      //根据当前 contentoffset获得index

      CGFloat width = scrollView.contentSize.width / self.categroyArray.count;

      CGFloat offsetX = scrollView.contentOffset.x;

      NSInteger index = offsetX / width;
      //选择cateview的index
      [_cateView selectAtIndex:index];
      }

    </pre>

    调用selectAtIndex:,该方法调用didSelectItemAtIndexPath:方法进行实现
    <pre>

    • (void)selectAtIndex:(NSInteger)index {

      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];

      [self collectionView:_cateView didSelectItemAtIndexPath:indexPath];
      }
      </pre>

    添加一个detailView:
    <pre>

    //
    // DetailCategroyBaseView.m
    // CategroyCollectionView
    //
    // Created by admin on 16/8/29.
    // Copyright © 2016年 Derrick_Qin. All rights reserved.
    //

    import "CategroyCell.h"

    import "DetailCategroyBaseView.h"

    import "DetailCell.h"

    @interface DetailCategroyBaseView () <UICollectionViewDelegate,
    UICollectionViewDataSource>
    @property(nonatomic, weak) UICollectionView *detailCateView;
    @property(nonatomic, strong) NSIndexPath *selectedIndexPath;
    @end

    static NSString *detailCateCellReuseId = @"detailCateCell";

    @implementation DetailCategroyBaseView

    • (instancetype)initWithFrame:(CGRect)frame {
      self = [super initWithFrame:frame];
      if (self) {

      [self setupCollectionViewWithFrame:frame];
      }
      return self;
      }

    • (void)setupCollectionViewWithFrame:(CGRect)frame {
      UICollectionViewFlowLayout *flowLayout =
      [[UICollectionViewFlowLayout alloc] init];

      flowLayout.itemSize =
      CGSizeMake(frame.size.width / (8 * 0.5), frame.size.height / 2);

      flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);

      flowLayout.minimumLineSpacing = 0;

      flowLayout.minimumInteritemSpacing = 0;

      UICollectionView *detailCateView =
      [[UICollectionView alloc] initWithFrame:frame
      collectionViewLayout:flowLayout];

      detailCateView.backgroundColor = [UIColor whiteColor];

      detailCateView.showsVerticalScrollIndicator = NO;

      detailCateView.showsHorizontalScrollIndicator = NO;

      detailCateView.bounces = NO;

      detailCateView.dataSource = self;

      detailCateView.delegate = self;

      _detailCateView = detailCateView;

      [self addSubview:detailCateView];

      [detailCateView registerClass:[DetailCell class]
      forCellWithReuseIdentifier:detailCateCellReuseId];
      }

    • (void)selectAtIndex:(NSIndexPath *)indexPath {

      _selectedIndexPath = indexPath;
      }

    pragma mark--数据源方法

    • (NSInteger)numberOfSectionsInCollectionView:
      (UICollectionView *)collectionView {
      return 1;
      }

    • (NSInteger)collectionView:(UICollectionView *)collectionView
      numberOfItemsInSection:(NSInteger)section {

      return self.categroyArray.count;
      }

    • (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
      cellForItemAtIndexPath:(NSIndexPath *)indexPath {

      DetailCell *cell = [collectionView
      dequeueReusableCellWithReuseIdentifier:detailCateCellReuseId
      forIndexPath:indexPath];

      NSString *title = self.categroyArray[indexPath.item];

      cell.title = title;

      if (indexPath.item == _selectedIndexPath.item) {

      cell.isSelected = YES;

      } else {
      cell.isSelected = NO;
      }

      return cell;
      }

    • (void)collectionView:(UICollectionView *)collectionView
      didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

      CategroyCell *selectedCell = (CategroyCell *)[collectionView
      cellForItemAtIndexPath:_selectedIndexPath];

      selectedCell.isSelected = NO;

      CategroyCell *cell =
      (CategroyCell *)[collectionView cellForItemAtIndexPath:indexPath];

      cell.isSelected = YES;

      _selectedIndexPath = indexPath;

      if ([self.delegate respondsToSelector:@selector(indexChange:andIndex:)]) {

      [self.delegate indexChange:self andIndex:indexPath.item];
      }
      }

    @end

    </pre>

    点击下拉按钮实现展现/隐藏明细分类栏:
    弹出明细分类栏的时候需要给北京设置一个蒙板
    <pre>

    cateView.changeBtnClick = ^(UIButton *changeBtn, BOOL btnIsSelected,
    NSIndexPath *indexPath) {

    if (btnIsSelected) {
    
      UIButton *coverView = [[UIButton alloc]
          initWithFrame:CGRectMake(
                            0, 40, [UIScreen mainScreen].bounds.size.width,
                            [UIScreen mainScreen].bounds.size.height - 40)];
    
      [coverView setBackgroundColor:[UIColor blackColor]];
      coverView.alpha = 0.45;
      [coverView addTarget:self
                    action:@selector(cancelDetailView)
          forControlEvents:UIControlEventTouchUpInside];
      _coverView = coverView;
      [self.view addSubview:coverView];
    
      DetailCategroyBaseView *detailView = [[DetailCategroyBaseView alloc]
          initWithFrame:CGRectMake(
                            0, 0, [UIScreen mainScreen].bounds.size.width, 80)];
    
      detailView.categroyArray = self.categroyArray;
      detailView.delegate = self;
    
      [self.view addSubview:detailView];
    
      _detailView = detailView;
    
      [detailView selectAtIndex:indexPath];
    
      [self.view bringSubviewToFront:_cateView];
    
      [UIView
          animateWithDuration:0.2
                   animations:^{
                     _detailView.frame = CGRectMake(
                         0, 40, [UIScreen mainScreen].bounds.size.width, 80);
                   }];
    } else {
    
      [_coverView removeFromSuperview];
    
      _coverView = nil;
    
      [self.view bringSubviewToFront:_cateView];
    
      [UIView animateWithDuration:0.2
          animations:^{
            _detailView.frame =
                CGRectMake(0, -40, [UIScreen mainScreen].bounds.size.width, 80);
    
          }
          completion:^(BOOL finished) {
    
            [_detailView removeFromSuperview];
    
            _detailView = nil;
    
          }];
    }
    

    };

    [self.view addSubview:cateView];
    }
    </pre>

    点击明细分类栏的cell触发事件:
    这边不适用block回调,使用代理的方式做到回传

    <pre>

    • (void)collectionView:(UICollectionView *)collectionView
      didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

      CategroyCell *selectedCell = (CategroyCell *)[collectionView
      cellForItemAtIndexPath:_selectedIndexPath];

      selectedCell.isSelected = NO;

      CategroyCell *cell =
      (CategroyCell *)[collectionView cellForItemAtIndexPath:indexPath];

      cell.isSelected = YES;

      _selectedIndexPath = indexPath;

      if ([self.delegate respondsToSelector:@selector(indexChange:andIndex:)]) {

      [self.delegate indexChange:self andIndex:indexPath.item];
      }
      }
      </pre>

    代理的协议方法的实现:
    <pre>

    • (void)indexChange:(DetailCategroyBaseView *)detailCategroyBaseView
      andIndex:(NSInteger)itemIndex {

      [self.view bringSubviewToFront:_cateView];

      [UIView animateWithDuration:0.2
      animations:^{

        _detailView.transform = CGAffineTransformMakeTranslation(0, 0);
      
      }
      completion:^(BOOL finished) {
      
        [_detailView removeFromSuperview];
      
      }];
      

      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:0];

      //记得动画效果去掉
      [self.collectionView
      scrollToItemAtIndexPath:indexPath
      atScrollPosition:UICollectionViewScrollPositionLeft
      animated:NO];

      [_cateView selectAtIndex:itemIndex];

      [_cateView changeBtnClick:nil];
      }

    </pre>

    具体的一些细节可以参考代码:
    https://github.com/DerrickQin2853/CategoryCollectionViewDemo

    感谢阅读

    相关文章

      网友评论

          本文标题:[iOS][Objective-C]:collectionVie

          本文链接:https://www.haomeiwen.com/subject/silwyttx.html