Animating custom-drawn UITableViewCell when entering edit mode

后端 未结 6 1544
攒了一身酷
攒了一身酷 2020-12-12 09:53

Background

First of all, much gratitude to atebits for their very informative blog post Fast Scrolling in Tweetie with UITableView. The post explains in detail how

相关标签:
6条回答
  • 2020-12-12 10:14

    To handle swiping as well: (self.editing && !self.showingDeleteConfirmation)

    0 讨论(0)
  • 2020-12-12 10:15

    For fully control on editing in your custom cell, you should override willTransitionToState method in your UITableViewCell subclass and check state mask

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

    also you can override 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];
    }
    
    0 讨论(0)
  • 2020-12-12 10:18

    How are you moving the text around currently? Or more specifically, in which UITableViewCell method are you performing the move?

    From my experience, overriding the layoutSubviews method and setting the frame here will automatically be wrapped in an animation.

    Eg:

    - (void)layoutSubviews {
        if (self.editing) {
            [titleLabel setFrame:CGRectMake(62, 6, 170, 24)];
        }
        else {
            [titleLabel setFrame:CGRectMake(30, 6, 200, 24)];
        }
        [super layoutSubviews];
    }
    
    0 讨论(0)
  • 2020-12-12 10:20

    I just had this question too: how to animate a custom editing mode? I didn't really like the solution here, so I decided to think a little bit and found a different solution. I don't know if it's better, but I prefer that one. So I decided to share it here:

    In the custom cell (inherit from UITableViewCell), just overload the 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];
    }
    

    I don't check if the editing value is the same, but that's just an idea how I did it.

    0 讨论(0)
  • 2020-12-12 10:20

    There are actually four edite states.

    UITableViewCellStateDefaultMask = 0

    UITableViewCellStateShowingEditControlMask = 1<<0 = 0b01 = 1 by setting the tableView.edit = YES

    UITableViewCellStateShowingDeleteConfirmationMask = 1<<1 = 0b10 = 2 by swiping to delete

    UITableViewCellStateShowingEditControlMask and UITableViewCellStateShowingDeleteConfirmationMask = (1<<1)&(1<<0) = 0b11 = 3 by setting the tableView.edit = YES and press the "stop" button

    What confused me is that when state 3 transfer to state 1, no selector would get called which make no use of self.showingDeleteConfirmation to change layout in iOS7.Therefore, in order to make clear between state 2 and state 3, I added a instance variable to implement it. It works great for me.

    -(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);
        }
    }
    
    0 讨论(0)
  • 2020-12-12 10:27

    Thanks to Craig's answer which pointed me in the right direction, I have a solution for this. I reverted my commit which moved the text position based on the editing mode and replaced it with a new solution that sets the entire content view to the correct position any time layoutSubviews is called, which results in an automatic animation when switching to and from edit mode:

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

    By doing it this way I was able to remove the setFrame: override found in ABTableViewCell.m because its former logic plus my additions are now found in layoutSubviews.

    I set a light grey background on the cells to verify a custom background works properly without allowing us to see behind it as it moves back and forth and it seems to work great.

    Thanks again to Craig and anyone else who has looked into this.

    GitHub commit for this solution: (link)

    0 讨论(0)
提交回复
热议问题