进入编辑模式时,为自定义绘制的UITableViewCell设置animation

背景

首先,非常感谢他们非常翔实的博客文章快速滚动在Tweetie与UITableView 。 这篇文章详细解释了开发人员如何能够从Tweetie的UITableViews中尽可能多的滚动性能。

目标

从博客文章( 原始 )链接的源代码开始( 我的github回购 ):

  1. 允许使用这些自定义单元格的UITableView切换到编辑模式,暴露从表中删除项目的UI。 ( github提交 )

  2. 当删除控件从左侧滑入时,将单元格的文本移到一边。 这是完整的,虽然文字跳来跳去没有animation。 ( github提交 )

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

问题

介绍这个animation完成目标3的最好方法是什么? 如果这样做可以保持我上次提交的逻辑,那将是非常好的,因为我希望只能移动视图的冲突部分,而任何不冲突的部分(如右alignment的文本)留在相同的地方或移动不同数量的像素。 如果上述不可能,那么撤销我的上一次提交,并用一个将整个视图向右滑动的选项来replace它也是可行的解决scheme。

我感谢任何人都可以提供的帮助,从快速指针和想法一直到代码片段或github提交。 当然,如果你愿意的话,欢迎你来回我的回购 。 我将继续参与这个问题,以确保任何成功的解决scheme致力于github,并在这里完整logging。 非常感谢你花时间陪伴!

更新的想法

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

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

感谢克雷格的回答 ,指出了我正确的方向,我有一个解决scheme。 我恢复了基于编辑模式移动文本位置的提交 ,并用一个新的解决scheme取代了它, 该解决scheme在layoutSubviews被调用时将整个内容视图设置到正确的位置,从而在切换到编辑模式和从编辑模式切换时导致自动animation:

- (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中find的setFrame:override,因为它之前的逻辑加上我的添加现在可以在layoutSubviews中find。

我在单元格上设置了一个浅灰色的背景,以validation自定义背景的正常工作,而不会让我们看到它背后,它来回移动,它似乎很好。

再次感谢Craig和其他已经看过这个的人。

GitHub提交这个解决scheme:( 链接 )

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

根据我的经验,覆盖layoutSubviews方法并在这里设置框架会自动包装成一个animation。

例如:

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

要完全控制自定义单元格中的编辑,应该在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]; } 

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

我也有这个问题:如何animation自定义编辑模式? 我不是很喜欢这里的解决scheme,所以我决定思考一下,find一个不同的解决scheme。 我不知道是不是更好,但我更喜欢那个。 所以我决定在这里分享一下:

在自定义单元格(从UITableViewCellinheritance),只是超载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]; } 

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

实际上有四个edite状态。

UITableViewCellStateDefaultMask = 0

UITableViewCellStateShowingEditControlMask = 1 << 0 = 0b01 = 1通过设置tableView.edit = YES

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

UITableViewCellStateShowingEditControlMask和UITableViewCellStateShowingDeleteConfirmationMask =(1 << 1)&(1 << 0)= 0b11 = 3通过设置tableView.edit = YES并按下“停止”button

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

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