UITableViewCell 上的动画

Posted

技术标签:

【中文标题】UITableViewCell 上的动画【英文标题】:Animation on UITableViewCell 【发布时间】:2019-03-18 05:00:42 【问题描述】:

我正在尝试将动画放在 UITableViewCell 中。动画是onClick table view cell将tableCell的frame变成tableview frame。

我有以下代码:

-(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) 

    ];

它工作正常,但在更改单元格的框架后,我也可以点击另一个我不想要的单元格。我怎样才能做到这一点?

【问题讨论】:

你的问题不清楚,你的意思是改变单元格的框架后我也可以点击另一个单元格? @vivekDas 请检查第二张图片,它是我更新的单元格。我禁用了表格视图滚动。如果我再次点击(假设在底部),则单元格(不是该单元格背面的这个单元格)被点击。清楚了吗? 我用过 [[cell superview] bringSubviewToFront:cell];成为选定单元格覆盖的方法 那么在过度单元格之后你想要什么?以及如何解除覆盖? @vivekDas 我想如果我再次点击打开的单元格,它应该会刷新并且它正在工作,但其他单元格也处于活动状态,这是我不想要的。我只想吸引当前单元格 【参考方案1】:

一种可能的解决方案是声明一个变量,该变量将保存一个扩展单元格的 indexPath 数组,如下所示

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

第二件事是添加和删除已扩展/未扩展的单元格,为此您必须更新您的 UITableView Delegate 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 Delegate 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,你只需要更改语法。

【讨论】:

当有人在那里度过了宝贵的时间@Wdp 移动时,至少有礼貌的回应 这不是我所期望的。不好意思推迟了。我想要什么我想根据我的代码禁用未选择的单元格 如果没有错,您的代码只是在进行扩展和折叠【参考方案2】:

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

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

您希望显示展开的单元格,当处于展开状态时,触摸会通过单元格视图并点击其后面的表格视图并重新触发didSelectRowAtIndexPath: tableview 委托方法(在展开后的其他单元格上一)。

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

    在单元格展开时将点击手势识别器添加到单元格中,以便吸收触摸,然后在使用后移除手势识别器。

-(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];

    继承 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];
            ];
        
    

从您的解释中我并没有真正理解的另一件事(正如 cmets 所提到的)是当用户点击展开的 tableview 单元格时您期望发生的事情。

【讨论】:

@Wdpmobile 很高兴它有帮助。随意投票或标记为解决方案,以便其他人在访问此帖子时可以看到答案是有帮助的。

以上是关于UITableViewCell 上的动画的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 上的圆形 UIImageView 在首次加载时不起作用

自定义 UITableViewCell 和 setSelected:animated 上的动画:

选择后,您可以为 UITableViewCell 上的高度变化设置动画吗?

如何淡入/淡出 UITableViewCell 上的 UILabel?

UITableViewCell 中 UIButton 的 NSIndexPath

如何在 UITableViewCell 上使用 CAGradientLayers