进入编辑模式时动画自定义绘制的UITableViewCell

时间:2009-04-13 01:51:41

标签: iphone objective-c cocoa-touch ios

背景

首先,非常感谢atebits提供的内容丰富的博文Fast Scrolling in Tweetie with UITableView。该帖子详细解释了开发人员如何能够在Tweetie中的UITableViews中尽可能多地压缩滚动性能。

目标

从博文(original)(my github repo)链接的源代码开始:

  1. 允许使用这些自定义单元格的UITableView切换到编辑模式,从而公开用于从表格中删除项目的UI。 (github commit

  2. 当删除控件从左侧滑入时,将单元格的文本移到一边。这是完整的,尽管文本在没有动画的情况下来回跳跃。 (github commit

  3. 将动画应用于上面目标2中的文字移动,以获得流畅的用户体验。这是我陷入困境的一步。

  4. 问题

    引入此动画以完成目标3的最佳方法是什么?如果可以通过保持逻辑与last commit的方式完成,那将是很好的,因为我希望只选择移动视图的冲突部分,而任何非冲突部分(例如右边)合理的文本)保持在同一个地方或移动不同数量的像素。如果无法实现上述目标,那么撤消我上一次提交并将其替换为将整个视图向右滑动的选项也是一种可行的解决方案。

    我感谢任何人都可以提供的任何帮助,从快速指针和想法一直到代码片段或github提交。当然,如果您愿意,欢迎您分叉my repo。我将继续参与这个问题,以确保任何成功的解决方案都致力于github,并在此完整记录。非常感谢你的时间!

    更新了想法

    自从我的第一篇文章以来,我一直在考虑这个问题,并意识到在视图中相对于其他文本项移动一些文本项可以撤消原始博客文章中解决的一些原始性能目标。所以在这一点上,我正在考虑一个解决方案,其中整个单个子视图动画到其新位置可能是最好的。

    其次,如果以这种方式完成,则可能存在子视图具有自定义颜色或渐变背景的实例。希望这可以通过这样一种方式完成:在正常位置,背景向左侧看不见,这样当视图向右滑动时,自定义背景在整个单元格中仍然可见。

6 个答案:

答案 0 :(得分:24)

感谢Craig's answer指出了我正确的方向,我有一个解决方案。我还原了commit,它根据编辑模式移动了文本位置,并将其替换为a new solution,可以在调用layoutSubviews时将整个内容视图设置为正确的位置,从而导致自动动画切换到编辑模式:

- (void)layoutSubviews
{
    CGRect b = [self bounds];
    b.size.height -= 1; // leave room for the separator line
    b.size.width += 30; // allow extra width to slide for editing
    b.origin.x -= (self.editing) ? 0 : 30; // start 30px left unless editing
    [contentView setFrame:b];
    [super layoutSubviews];
}

通过这样做,我能够删除在ABTableViewCell.m中找到的setFrame:override,因为现在可以在layoutSubviews中找到它以前的逻辑加上我的添加内容。

我在单元格上设置了浅灰色背景,以验证自定义背景是否正常工作,而不允许我们在它后面移动时看到它背后,它看起来效果很好。

再次感谢Craig和其他任何研究过此事的人。

GitHub提交此解决方案:(link

答案 1 :(得分:10)

您目前如何移动文字?或者更具体地说,你在哪个UITableViewCell方法中执行移动?

根据我的经验,覆盖layoutSubviews方法并在此处设置框架将自动包装在动画中。

例如:

- (void)layoutSubviews {
    if (self.editing) {
        [titleLabel setFrame:CGRectMake(62, 6, 170, 24)];
    }
    else {
        [titleLabel setFrame:CGRectMake(30, 6, 200, 24)];
    }
    [super layoutSubviews];
}

答案 2 :(得分:9)

要完全控制自定义单元格中的编辑,您应该覆盖UITableViewCell子类中的willTransitionToState方法并检查状态掩码

- (void)willTransitionToState:(UITableViewCellStateMask)state
{
    NSString *logStr = @"Invoked";
    if ((state & UITableViewCellStateShowingEditControlMask)
        != 0) {
        // you need to move the controls in left
        logStr = [NSString stringWithFormat:@"%@
                  %@",logStr,@"UITableViewCellStateShowingEditControlMask"];
    }
    if ((state & UITableViewCellStateShowingDeleteConfirmationMask)
        != 0) {
        // you need to hide the controls for the delete button
        logStr = [NSString stringWithFormat:@"%@
                  %@",logStr,@"UITableViewCellStateShowingDeleteConfirmationMask"];
    }
    NSLog(@"%@",logStr);
    [super willTransitionToState:state];
}

您也可以覆盖layoutSubviews

- (void)layoutSubviews {
    // default place for label
    CGRect alarmTimeRect = CGRectMake(37, 7, 75, 30);
    if (self.editing && !self.showingDeleteConfirmation) {
        // move rect in left
        alarmTimeRect = CGRectMake(77, 7, 75, 30);
    }
    [alarmTimeLabel setFrame:alarmTimeRect];
    [super layoutSubviews];
}

答案 3 :(得分:8)

要处理滑动:( self.editing&&!self.showingDeleteConfirmation)

答案 4 :(得分:3)

我也有这个问题:如何设置自定义编辑模式的动画?我真的不喜欢这里的解决方案,所以我决定稍微思考一下,找到一个不同的解决方案。我不知道它是否更好,但我更喜欢那个。所以我决定在这里分享一下:

在自定义单元格中(从UITableViewCell继承),只需重载setEditing:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];

    if (animated) {
        [UIView beginAnimations:@"setEditingAnimation" context:nil];
        [UIView setAnimationDuration:0.3];
    }

    if (editing) {
        /* do your offset and resize here */
    } else {
        /* return to the original here*/
    }

    if (animated)
        [UIView commitAnimations];
}

我不会检查编辑值是否相同,但这只是一个想法我是如何做到的。

答案 5 :(得分:0)

实际上有四种编辑状态。

UITableViewCellStateDefaultMask = 0

通过设置tableView.edit = YES

,UITableViewCellStateShowingEditControlMask = 1<< 0 = 0b01 = 1

通过滑动删除UITableViewCellStateShowingDeleteConfirmationMask = 1<< 1 = 0b10 = 2

通过设置tableView.edit = YES并按下“停止”按钮

UITableViewCellStateShowingEditControlMask和UITableViewCellStateShowingDeleteConfirmationMask =(1<< 1)&(1<< 0)= 0b11 = 3

让我感到困惑的是,当状态3转移到状态1时,没有选择器会被调用而不使用self.showingDeleteConfirmation来改变iOS7中的布局 。因此,为了弄清楚状态2和状态3,我添加了一个实例变量来实现它。它对我很有用。

-(void)willTransitionToState:(UITableViewCellStateMask)state{
    [super willTransitionToState:state];

    //Custom delete button from
    //http://stackoverflow.com/questions/19159476/uitableviewcelldeleteconfirmationcontrol-issue
    if((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask){
        [self recurseAndReplaceSubViewIfDeleteConfirmationControl:self.subviews];
        [self performSelector:@selector(recurseAndReplaceSubViewIfDeleteConfirmationControl:) withObject:self.subviews afterDelay:0];
    }

    _swipeDelete = NO;

    if(state==2){
        //Swipe to delete confirm
        _swipeDelete = YES;
    }

    if(state==3){
        //Edit state to delete confirm
    }
}

- (void)layoutSubviews{

    [super layoutSubviews];

    self.contentView.frame = CGRectMake(10, 5.0, 300, self.frame.size.height - 10);

    if(self.editing){
        self.contentView.frame = CGRectMake(40, 5.0, 270, self.frame.size.height - 10);
    }

    if(_swipeDelete){
        self.contentView.frame = CGRectMake(10, 5.0, 300, self.frame.size.height - 10);
    }
}