UITableViewCell 子类,在代码中绘制,动画中的删除按钮

Posted

技术标签:

【中文标题】UITableViewCell 子类,在代码中绘制,动画中的删除按钮【英文标题】:UITableViewCell subclass, drawn in code, animate Delete button in 【发布时间】:2011-04-21 10:27:28 【问题描述】:

我正在开发一个自定义 UITableViewCell 子类,其中所有内容都是在代码中绘制的,而不是使用 UILabel 等。(这部分是学习练习,部分是因为在代码中绘制要快得多。我知道对于几个标签它不会有很大的不同,但最终我想将其推广到更复杂的单元格。)

目前我正在为删除按钮动画而苦苦挣扎:如何在删除按钮滑入时使单元格收缩。

首先,我正在绘制单元格内容视图的自定义子视图。一切都在那个子视图中绘制。

我通过在单元格本身上捕获 layoutSubviews 来设置子视图的大小,并执行以下操作:

- (void)layoutSubviews

    [super layoutSubviews];
    CGRect b = [self.contentView bounds];
    [subcontentView setFrame:b];    

我这样做而不是仅仅设置自动调整掩码,因为它在测试中似乎更可靠,但如果需要,我可以在测试中使用自动调整掩码方法。

现在,当有人点击减号时,默认情况是视图被压扁。

我可以通过在设置我的手机时拨打电话来避免这种情况

subcontentView.contentMode = UIViewContentModeRedraw;

这给了我正确的最终结果(我的自定义视图以新大小重绘,并且布局正确,就像我发布的第一张图片一样),但是过渡的动画令人不快:它看起来像单元格拉伸和缩小到原来的大小。

我知道为什么动画会这样工作:Core Animation 不会要求您的视图重绘每一帧,它会让它重绘动画的结束位置,然后进行插值以找到中间位。

另一种解决方案是这样做

subcontentView.contentMode = UIViewContentModeLeft;

这只是在我的单元格上绘制了删除按钮,所以它覆盖了它的一部分。

如果我也实现

- (void) didTransitionToState:(UITableViewCellStateMask)state

    [self setNeedsDisplay];

一旦删除按钮在单元格中滑动,就会“跳转”到正确的大小。这样就没有很好的滑动动画,但至少我最后得到了正确的结果。

我想我可以在删除按钮出现的同时运行我自己的动画,临时创建另一个视图,其中包含旧尺寸的视图图像的副本,将我的视图设置为新尺寸,并在它们之间淡入淡出——即这样会有一个很好的交叉淡入淡出而不是急剧跳跃。有人用过这种技术吗?

现在,您可能会问为什么我不能使用contentStretch 属性并给它一个区域来调整大小。问题是我正在做一些相当通用的东西,所以它并不总是可能的。在这个特定的示例中它可以工作,但更复杂的单元格可能不会。

所以,我的问题(在所有这些背景之后)是:在这种情况下你会做什么?有没有人有用于自定义绘制单元格的动画删除按钮?如果不是,最好的妥协是什么?

【问题讨论】:

我得到了它的工作,虽然我现在没有代码。可以私信我吗 【参考方案1】:

这终于对我有用了。在 UITableViewCell 的子类中

subDrawContentView.contentMode = UIViewContentModeLeft;

覆盖布局子视图方法

- (void)layoutSubviews 

    CGRect b = [subDrawContentView bounds];
    b.size.width = (!self.showingDeleteConfirmation) ? 320 : 300;
    [subDrawContentView setFrame:b];
    [subDrawContentView setNeedsDisplay];

    [super layoutSubviews];

【讨论】:

【参考方案2】:

所以我先贴代码再解释:

-(void)startCancelAnimation
    [cancelButton setAlpha:0.0f];
    [cancelButton setFrame:CGRectMake(320., cancelButton.frame.origin.y, cancelButton.frame.size.width, cancelButton.frame.size.height)];
    cancelButton.hidden=NO;

    [UIView animateWithDuration:0.4
                     animations:^(void)
                    [progressView setFrame:CGRectMake(progressView.frame.origin.x, progressView.frame.origin.y, 159.0, progressView.frame.size.height)];
                    [text setFrame:CGRectMake(text.frame.origin.x, text.frame.origin.y, 159.0, text.frame.size.height)];
                    [cancelButton setFrame:CGRectMake(244., cancelButton.frame.origin.y, cancelButton.frame.size.width, cancelButton.frame.size.height)];
                         [cancelButton setAlpha:1.0f];    
                       ];


-(void)stopCancelAnimation
    [UIView animateWithDuration:0.4
                     animations:^(void)
                        [cancelButton setFrame:CGRectMake(320., cancelButton.frame.origin.y, cancelButton.frame.size.width, cancelButton.frame.size.height)];
                         [cancelButton setAlpha:0.0f];
                     completion:^(BOOL completion) 
                         cancelButton.hidden=YES;
                         [cancelButton setAlpha:1.0f];
                         [progressView setFrame:CGRectMake(progressView.frame.origin.x, progressView.frame.origin.y, DEFAULT_WIDTH_PROGRESS, progressView.frame.size.height)];
                         [text setFrame:CGRectMake(text.frame.origin.x, text.frame.origin.y, DEFAULT_WIDTH_TEXT, text.frame.size.height)];
                        
     ];



-(void)decideAnimation
    if([cancelButton isHidden])
        [self startCancelAnimation];
    
    else
        [self stopCancelAnimation];
    

所以我有一个如下所示的按钮:

我有一个IBOutlet。我正在做的是调整UIProgressViewUITextField 的大小(你可以调整任何你想要的大小)。至于代码非常简单,但是如果您需要任何帮助来了解发生了什么,请询问。另外,不要忘记将 Swip Gesture 添加到 UITableView... 像这样:

    UISwipeGestureRecognizer *gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
    gesture.numberOfTouchesRequired=1;
    gesture.direction = UISwipeGestureRecognizerDirectionRight;
    [table addGestureRecognizer:gesture];
    [gesture release];

最后是做这一切的方法:

-(void)didSwipe:(UIGestureRecognizer *)gestureRecognizer 

        if (gestureRecognizer.state == UIGestureRecognizerStateEnded) 
            //Get the cell of the swipe...
            CGPoint swipeLocation = [gestureRecognizer locationInView:self.table];
            NSIndexPath *swipedIndexPath = [self.table indexPathForRowAtPoint:swipeLocation];
            UITableViewCell* swipedCell = [self.table cellForRowAtIndexPath:swipedIndexPath];
            //Make sure its a cell with content and not an empty one.
            if([swipedCell isKindOfClass:[AMUploadsTableViewCell class]])
                 // It will start the animation here
                [(AMUploadsTableViewCell*)swipedCell decideAnimation];
                // Do what you want :)
            
        
    

如您所见,整个动画是手动创建的,因此您可以准确控制您想要的内容。 :)

【讨论】:

以上是关于UITableViewCell 子类,在代码中绘制,动画中的删除按钮的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 阴影未为某些单元格绘制

UITableViewCell 自定义CG绘制iOS 7

子类 UITableViewCell - backgroundView 涵盖了我在 drawRect 中所做的任何事情

带有在代码中绘制的自定义图像的 UITableViewCell

在 UITableViewCell 子类中添加 CAGradientLayer 需要帮助

无法在 UITableViewCell 的 drawRect 中绘制