UITableViewCell上的动画

时间:2019-03-18 05:00:43

标签: ios objective-c uitableview animation

我正在尝试将动画放入UITableViewCell中。动画是onClick表格视图单元格将tableCell的框架更改为tableview框架。

我有以下代码:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 10;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell*cell = [tableView cellForRowAtIndexPath:indexPath];

    if(cell.frame.size.height == tableView.bounds.size.height){
        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }else{
        cell.frame = tableView.bounds;
        [[cell superview] bringSubviewToFront:cell];
    }

    [UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
         [self.view layoutIfNeeded];
    } completion:^(BOOL finished) {

    }];
}

它工作正常,但是在更改单元格的框架后,我也可以轻按另一个我不想要的单元格。我该如何实现?

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:2)

一种可能的解决方案是声明一个变量,该变量将保存像这样的展开单元格的indexPath数组

// Will hold the indexPath of expanded cell
var expandedCell : [IndexPath] = []

第二件事是添加/删除未扩展的单元格,而要做的就是更新UITableView委托didSelectRowAt

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let index = expandedCell.firstIndex { (localIndexPath) -> Bool in
        return indexPath == localIndexPath
    }
    if let index = index  {
        expandedCell.remove(at: index)
    } else {
        expandedCell.append(indexPath)
    }
    tableviewMessageList.reloadRows(at: [indexPath], with: .fade)
} 

最后,您必须添加另一个UITableView委托heightForRowAt以返回单元格的高度(如果单元格的indexPath在数组中),它将返回扩展后的大小,否则返回单元格的正常大小,如下所示: -

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if expandedCell.contains(indexPath) {
        return tableView.frame.height
    }
    return 200.0 //NormalHeight
}
  

注意:我的回答是在Swift中,但是相同的原理将适用于Objective-C,您只需要更改语法即可。

答案 1 :(得分:0)

总的来说,我认为更好的方法是使用单独的视图全屏显示单元格详细信息,尽管您可能会有一些限制,要求您以这种方式进行操作。话虽如此,请在下面找到我的答案。

这是我收集到的当前问题:

您想显示单元格已展开,并且在这种扩展状态下,触摸会遍历单元格视图,并击中其后的表格视图,然后重新触发didSelectRowAtIndexPath: tableview委托方法(在除扩展的)。

这些是我看到的几种可能的解决方案:

  1. 在单元格展开时向其添加一个轻击手势识别器,以便吸收触摸,然后在消耗完该手势识别器后将其删除。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnExpandedCell:)];
    [cell addGestureRecognizer:tap];
    cell.frame = tableView.bounds;
    [[cell superview] bringSubviewToFront:cell];
    UIView *bgView = [[UIView alloc] init];
    bgView.backgroundColor = [UIColor purpleColor];
    cell.selectedBackgroundView = bgView;
    [UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
}

-(void)didTapOnExpandedCell:(UIGestureRecognizer *)recognizer {
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
    // do whatever you were planning on doing when tapping on the
    // expanded cell
    [self.tableView reloadRowsAtIndexPaths:@[self.tableView.indexPathForSelectedRow] withRowAnimation:UITableViewRowAnimationNone];
    [cell removeGestureRecognizer:recognizer];
}
  1. 子类UITableViewCell并覆盖touchesBegan:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    R4NTableViewCell *cell = (R4NTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
    cell.frame = tableView.bounds;
    [[cell superview] bringSubviewToFront:cell];
    UIView *bgView = [[UIView alloc] init];
    bgView.backgroundColor = [UIColor purpleColor];
    cell.selectedBackgroundView = bgView;
    [UIView animateWithDuration:0.5 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
}

// in R4NTableViewCell.m implementation override touchesBegan
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // if we're not selected, don't intercept the touch so the tableview can handle it
    // calling back to super will give the default tableview behavior and get our delegate callback
    if (self.selected == NO) {
        self.frameBeforeExpansion = self.frame;
        [super touchesBegan:touches withEvent:event];
    } else { // we're in the expanded state so intercept the touch
        NSSet <UITouch *> *singleTouches = [[event allTouches] objectsPassingTest:^BOOL(UITouch * _Nonnull obj, BOOL * _Nonnull stop) {
            return obj.tapCount == 1;
        }];
        if (singleTouches.count > 0) {
            // the user single tapped our view
            [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.7 initialSpringVelocity:0.2 options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.frame = self.frameBeforeExpansion;
                [self.superview layoutIfNeeded];
            } completion:^(BOOL finished) {
                [self setSelected:NO];
                self.backgroundView.backgroundColor = [UIColor greenColor];
            }];
        }
    }
}

从您的解释中我并不能真正理解的另一件事(如所提到的评论)是您希望用户点击展开的表格视图单元格时发生的事情。