CollectionViewCell中的约束动画问题

时间:2017-10-27 17:29:55

标签: ios objective-c uiview uicollectionview uicollectionviewcell

不幸的是,我仍然遇到限制问题......我绝对是我的问题,但我真的无法理解他们......

我用自定义单元格创建了一个UICollectionView。

在单元格中,我插入了一个带有所有约束的UIView。

Uiview高度约束默认设置为ZERO,并根据collectionM从NSMutableArray收集的数据进行更改

在cellForItemAtIndexPath方法中增加或减少自定义单元格中的uiview高度...

一切运作良好,数据收集到完美但我不明白为什么每次滚动collectionView时uiview高度动画都会继续..

我希望在显示collectionView时动画视图的高度,但是当我向后或向前滚动时我不想动画...我创建了一个视频来向您展示

https://streamable.com/d32fy

我不明白我错在哪里,是不是因为一些我无法理解的限制和动画问题而陷入困境的日子......

这是我正在使用的代码

主视图控制器

-(void)setupCollectionView {

    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.minimumLineSpacing = 2;
    flowLayout.minimumInteritemSpacing = 0;
    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    _chartCollection = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout];
    [_chartCollection registerClass:[KPHomeChartCell class] forCellWithReuseIdentifier:kChartCellIdentifier];
    _chartCollection.backgroundColor = [UIColor clearColor];
    _chartCollection.delegate = self;
    _chartCollection.dataSource = self;
    _chartCollection.pagingEnabled = YES;
    _chartCollection.showsHorizontalScrollIndicator = NO;
    _chartCollection.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:_chartCollection];

    self.topChartCollectionAnchor = [self.chartCollection.topAnchor constraintEqualToAnchor:self.customSwitch.bottomAnchor constant:20];
    self.topChartCollectionAnchor.active = YES;
    [self.chartCollection.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:30].active = YES;
    [self.chartCollection.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES;
    [self.chartCollection.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-35].active = YES;

    [self buildYAxis];
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
    KPHomeChartCell *chartCell = [collectionView dequeueReusableCellWithReuseIdentifier:kChartCellIdentifier forIndexPath:indexPath];

    NSInteger n = [[self returnXAxis][indexPath.item] integerValue];
    UILabel *yLabelValue = (UILabel *)[self viewWithTag:n];

    chartCell.leftBarHeightConstraint.constant = [self offsetBarFromChart:collectionView] - yLabelValue.center.y;

    chartCell.rightBarHeightConstraint.constant = [self offsetBarFromChart:collectionView] - yLabelValue.center.y +30;

    return chartCell;
}

自定义CollectionViewCell

-(void)animateHeightOfBarWithConstant {
  // Crea la linea a tratti per ogni barra
    CAShapeLayer *dashedLine = [CAShapeLayer layer];
    CGMutablePathRef thePath = CGPathCreateMutable();
    CGPathMoveToPoint(thePath, nil, 0, 0);
    CGPathAddLineToPoint(thePath, nil, 0, self.contentView.frame.size.height);

    dashedLine.path = thePath;
    CGPathRelease(thePath);
    dashedLine.lineDashPattern = @[@4];
    dashedLine.strokeColor =  [UIColor colorWithHexString:@"#FFFFFF" setAlpha:.1].CGColor;
    [self.contentView.layer addSublayer:dashedLine];


    // BUILD BAR UIVIEW
    _bar = [[UIView alloc] init];
    _bar.layer.cornerRadius = 4;
    _bar.translatesAutoresizingMaskIntoConstraints = NO;
    CGFloat barWidth = 15;
    [self.contentView addSubview:_bar];

    dispatch_async(dispatch_get_main_queue(), ^{
                dashedLine.frame = CGRectMake(_bar.center.x, 0, self.contentView.frame.size.width , 15);
            });


    [self.bar.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor].active = YES;
    [self.bar.widthAnchor constraintEqualToConstant:barWidth].active = YES;
    [self.bar.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor constant:-13.5].active = YES;

     self.leftBarHeightConstraint = [self.bar.heightAnchor constraintEqualToConstant:0];
     self.leftBarHeightConstraint.active = YES;

     [UIView animateWithDuration:.9 animations:^{
         [self.contentView layoutIfNeeded];
    }];
}

2 个答案:

答案 0 :(得分:1)

如果只需要1.动画,请执行以下操作:

  1. 在viewDidAppear中以秒为单位获取并保存当前时间NSTimeInterval startTime = [[NSDate date] timeIntervalSinceReferenceDate];
  2. 如果初始动画的时间已过,则在cellForIndexPath中 - > ([NSDate date] timeintervalSinceReferenceData] - startTime)> animationTime将视图的大小设置为最终动画状态(因此不会发生动画)
  3. function animateHeightOfBarWithConstant()应该有一个动画参数(BOOL)。如果设置为YES,则执行动画(动画时间非零),如果发送NO,动画时间为0或使用[UIView performWithoutAnimation:]
  4. 在单元格上使用-prepareForReuse()方法。单元格被重用,您需要设置正确的开始条件或在cellForIndexPath方法中设置所有属性。

答案 1 :(得分:1)

您可以尝试此代码

主视图控制器

@interface MainViewController () <UITableViewDelegate>

@property (nonatomic, assign) NSUInteger lastCellDisplayedIndex;

@end

@implementation MainViewController

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
  _lastCellDisplayedIndex = indexPath.row;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
  KPHomeChartCell *chartCell = [collectionView dequeueReusableCellWithReuseIdentifier:kChartCellIdentifier forIndexPath:indexPath];

  NSInteger n = [[self returnXAxis][indexPath.item] integerValue];
  UILabel *yLabelValue = (UILabel *)[self viewWithTag:n];

  chartCell.leftBarHeightConstraint.constant = [self offsetBarFromChart:collectionView] - yLabelValue.center.y;

  chartCell.rightBarHeightConstraint.constant = [self offsetBarFromChart:collectionView] - yLabelValue.center.y +30;

  if (_lastCellDisplayedIndex >= indexPath) {
    [chartCell updateHeightOfBarAnimated:NO];
  } else {
    [chartCell updateHeightOfBarAnimated:YES];
  }

  return chartCell;
}

@end

自定义CollectionViewCell

-(void)updateHeightOfBarAnimated:(BOOL)animated {
  // Crea la linea a tratti per ogni barra
  CAShapeLayer *dashedLine = [CAShapeLayer layer];
  CGMutablePathRef thePath = CGPathCreateMutable();
  CGPathMoveToPoint(thePath, nil, 0, 0);
  CGPathAddLineToPoint(thePath, nil, 0, self.contentView.frame.size.height);

  dashedLine.path = thePath;
  CGPathRelease(thePath);
  dashedLine.lineDashPattern = @[@4];
  dashedLine.strokeColor =  [UIColor colorWithHexString:@"#FFFFFF" setAlpha:.1].CGColor;
  [self.contentView.layer addSublayer:dashedLine];


  // BUILD BAR UIVIEW
  _bar = [[UIView alloc] init];
  _bar.layer.cornerRadius = 4;
  _bar.translatesAutoresizingMaskIntoConstraints = NO;
  CGFloat barWidth = 15;
  [self.contentView addSubview:_bar];

  dispatch_async(dispatch_get_main_queue(), ^{
    dashedLine.frame = CGRectMake(_bar.center.x, 0, self.contentView.frame.size.width , 15);
  });


  [self.bar.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor].active = YES;
  [self.bar.widthAnchor constraintEqualToConstant:barWidth].active = YES;
  [self.bar.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor constant:-13.5].active = YES;

  self.leftBarHeightConstraint = [self.bar.heightAnchor constraintEqualToConstant:0];
  self.leftBarHeightConstraint.active = YES;

  if (animated) {
    [UIView animateWithDuration:.9 animations:^{
      [self.contentView layoutIfNeeded];
    }];
  } else {
    [self.contentView layoutIfNeeded];
  }
}

- (void)prepareForReuse {
    if (_bar) {
      [_bar removeFromSuperview];
      _bar = nil;
    }
  }

仅在updateHeightOfBarAnimated

中使用cellForItemAtIndexPath