Iphone 进入编辑模式时设置自定义绘制UITableViewCell的动画 背景

Iphone 进入编辑模式时设置自定义绘制UITableViewCell的动画 背景,iphone,objective-c,cocoa-touch,ios,Iphone,Objective C,Cocoa Touch,Ios,首先,非常感谢他们的博文内容丰富。这篇文章详细解释了开发人员是如何从中的UITableView中挤出尽可能多的滚动性能的 目标 从博客帖子()链接的源代码开始: 允许使用这些自定义单元格的UITableView切换到编辑模式,显示用于从表中删除项的UI。() 当删除控件从左侧滑入时,将单元格文本移到一旁。这就完成了,尽管文本在没有动画的情况下来回跳跃。() 将动画应用于上述目标2中的文本移动,以获得平滑的用户体验。这是我陷入困境的一步 问题 介绍此动画以完成目标3的最佳方式是什么?如果能够

首先,非常感谢他们的博文内容丰富。这篇文章详细解释了开发人员是如何从中的UITableView中挤出尽可能多的滚动性能的

目标 从博客帖子()链接的源代码开始:

  • 允许使用这些自定义单元格的UITableView切换到编辑模式,显示用于从表中删除项的UI。()

  • 当删除控件从左侧滑入时,将单元格文本移到一旁。这就完成了,尽管文本在没有动画的情况下来回跳跃。()

  • 将动画应用于上述目标2中的文本移动,以获得平滑的用户体验。这是我陷入困境的一步

  • 问题 介绍此动画以完成目标3的最佳方式是什么?如果能够以一种不影响逻辑的方式完成,那就太好了,因为我喜欢只移动视图中冲突部分的选项,而任何非冲突部分(如右对齐文本)保持在同一位置或移动不同数量的像素。如果上述操作不可行,那么撤消上次提交并用将整个视图向右滑动的选项替换它也是一个可行的解决方案

    我感谢任何人能提供的任何帮助,从快速提示和想法到代码片段或github提交。当然,如果您愿意,欢迎您使用fork。我将继续参与这个问题,以确保任何成功的解决方案都会提交给github,并在这里完整记录。非常感谢您抽出时间

    更新的想法 自从我第一篇博文以来,我就一直在思考这个问题,并意识到在视图中相对于其他文本项移动一些文本项可能会撤销原始博文中解决的一些原始性能目标。因此,在这一点上,我想一个解决方案,其中整个单一的子视图是动画到它的新位置可能是最好的一个


    其次,如果以这种方式执行,则可能会出现子视图具有自定义颜色或渐变背景的情况。希望这可以通过一种方式来实现,即在其正常位置,背景向左延伸到看不见的位置,这样当视图向右滑动时,自定义背景在整个单元格中仍然可见。

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

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

    例如:

    多亏它为我指明了正确的方向,我才有了解决这个问题的办法。我恢复了基于编辑模式移动文本位置的设置,并将其替换为在调用LayoutSubView时将整个内容视图设置为正确位置的设置,从而在切换到编辑模式和从编辑模式切换时生成自动动画:

    - (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,因为它以前的逻辑加上我添加的内容现在可以在LayoutSubview中找到

    我在单元格上设置了一个浅灰色背景,以验证自定义背景是否正常工作,而不允许我们看到它的后面,因为它前后移动,并且似乎工作得很好

    再次感谢克雷格和其他调查此事的人


    GitHub提交此解决方案:()

    也处理刷卡:(self.editing&!self.showingDeleteConfirmation)

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

    在自定义单元格(从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];
    }
    

    我不检查编辑值是否相同,但这只是我的想法

    要完全控制自定义单元格中的编辑,应在UITableViewCell子类中重写WillTransitionState方法并选中状态掩码

    - (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];
    }
    
    还可以替代布局子视图

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

    实际上有四个编辑状态

    UITableViewCellStateDefaultMask=0


    UITableViewCellStateShowingEditControlMask=1Hi Craig,绘图当前在FirstLastExampleTableViewCell的-(void)drawContentView:(CGRect)r方法中完成,该方法是从ABTableViewCell对UITableViewCell的-(void)drawRect:(CGRect)r方法的重写中调用的。代码在这里:在使用多个子视图的情况下,您的解决方案看起来不错,但这里有一个包含整个单元格内容的自定义绘制子视图。可能布局子视图也将是这方面的关键,我将对此进行调查,并将感谢任何其他想法,谢谢!我不确定使用他们的方法这会有多好,因为文本是直接绘制到屏幕上的,而不是嵌入到UIView或任何支持CoreAnimation的对象中。与仅使用UITextField/UITextView相比,这种方法是否有显著的改进?再次感谢Craig,这是朝着正确方向迈出的一大步!请参阅我发布的答案,了解我是如何使用此信息的。在我链接的博客文章中,也有关于性能的更多解释;对于复杂的单元布局,性能提升似乎最为显著。您的解决方案看起来非常完美,这正是我所想的。很高兴它成功了我有一个确切的问题,使用确切的代码。如果我在头撞墙几个小时之前先看看这里,我就不会额头上有瘀伤了。你的解决方案非常有效。谢谢。如果你正在使用自动布局,并且只想调整一个约束,这也很有效-它将使约束调整具有动画效果。谢谢ben,这非常有效!我相应地更新了我的github项目
    - (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];
    }
    
    -(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);
        }
    }