How can I flip an iOS UITableViewCell?

2019-02-05 14:21发布

问题:

I have a tableview with a number of cells. Each cell has a little info "i" button, which I would like the user to be able to click in order to edit the information in that cell, by "flipping" the cell from the right.

I have a separate table cell XIB for each of the two possible cell states, and cellForRowAtIndexPath provides the correct XIB (with a different cell identifier) depending on whether the cell is supposed to be in the regular view or the detail/edit view. This works fine using, e.g., reloadRowsAtIndexPaths to reflect the changed state when the "i" button is pressed.

But I just can't figure out how to animate a flip when the cell's "i" button is pressed. Flipping isn't one of the options for "withRowAnimation" in reloadRowsAtIndexPaths. And using a standard animation approach like UIView animateWithDuration doesn't work: reloadRowsAtIndexPaths just causes the relevant cell to reload instantly, ignoring the animation instructions. I even tried to use drawViewHierarchyInRect to pick up the cell's future state as an image, but I couldn't get the cell to redraw itself quickly enough to be picked up by drawViewHierarchyInRect (and I don't want the user to actually see the result of the animation before the animation).

Does anyone have an idea of how to handle this?

EDIT

To summarize, the challenge I'm having is: is there another way to swap UITableView cell contents with a different UITableViewCell Xib besides reloadRowsAtIndexPaths (which breaks animations), without causing trouble with the IBOutlets of the new Xib? (Loading it as a Nib into a subview seems to break the IBOutlets.) The answers so far haven't addressed this.

回答1:

It will be complicated if u use two subclassed UITableViewCell, instead use a single subclassed UITableViewCell, and perform flip-animation for example,

let xib contains the subclass UITableViewCell in its contentView add two views

  1. normal View
  2. Flipped View

in this view's add the contents what u want to display, and make sure both hav outlet in the cell for example that i took

in the above two view first one View-FlipView and its contents label and button and second one is also same as first view, top view should be the normalView
connect the button actions to cell and u just perform like below in custom cell

  //flip the view to flipView
- (IBAction)flipButtonAction:(UIButton *)sender
  {

    [UIView transitionWithView:self.contentView duration:0.6 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
    [self.contentView insertSubview:_flipView aboveSubview:_normalView];
    } completion:^(BOOL finished) {

    }];
   }

   //flip the view back to normalView
 - (IBAction)flipBackButtonAction:(id)sender
  {

     [UIView transitionWithView:self.contentView duration:0.6 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
      [self.contentView insertSubview:_normalView aboveSubview:_flipView];
    } completion:^(BOOL finished) {

   }];
  }  

and it will look like something below

any problem just comment ... :) hope this helps u .. :)



回答2:

You probably don't want to reload the table's data to flip any given cell. Your cells should be able to flip "on their own." So you'll need to subclass UITableViewCell and in your subclass you'll have something like a flip function, that does some animations of the cell's subviews.

Now here's a trick with flip animations. You can't just change the view hierarchy and flip at the same time, or you'll see the "back side" of your view at the wrong time during the animation. Use two animations in a row:

[UIView animateWithDuration:... {
    // Flip the content "half way" by rotating 90 degrees about the y axis.
    // At the end of this animation your view will be perpendicular to the
    // screen and *not visible*.
    contentView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);
} completion: {
    // Here you can rearrange your views (remember the view isn't visible
    // right now!
    //
    // When the "back side" views are all ready, you can kick off the second
    // half of the flip animation.
    [UIView animateWithDuration:... {
        // Flip *back* to the identity (not all the way around to M_PI)
        // because if you flip all the way around your views will actually
        // be flipped.  You don't want that.  Users will instinctively see
        // the movement as *continuous* and interpret the flip back and forth
        // animation as one continuous rotation all the way around.
        contentView.layer.transform = CATransform3DIdentity;
    }
}


回答3:

Swift 4:

@IBAction func flipButtonAction(_ sender: UIButton) {

    UIView.transition(with: contentView, duration: 0.6, options: .transitionFlipFromRight, animations: {() -> Void in
        self.contentView.insertSubview(flipView, aboveSubview: normalView)
    }, completion: {(_ finished: Bool) -> Void in
    })
}

//flip the view back to normalView

@IBAction func flipBackButtonAction(_ sender: Any) {

    UIView.transition(with: contentView, duration: 0.6, options: .transitionFlipFromLeft, animations: {() -> Void in
        self.contentView.insertSubview(normalView, aboveSubview: flipView)
    }, completion: {(_ finished: Bool) -> Void in
    })
}


回答4:

I can't see why you couldn't use [UIView animateWithDuration...].

You could have two UIViews in each cell who's scale you animate. The first would be visible and the second would be hidden

At the half-way point of the animation, simply hide the first UIView and unhide the second and continue the animation from there.