UIViewController Containment with animation like Google+

半世苍凉 提交于 2019-12-21 22:26:18

问题


The best way to understand what I'm trying to explain is to open Google+ app and tap anywhere in background of a post displayed in the main stream of posts.

When you tap it, the entire post moves itself at the center of the screen with a nice animation and it loads the post's comments below it.

I think this is a common UIViewController containment scenario, where one UIViewController is inside another. But how the post can moves it animately and "transfering" itself inside the contained view controller?

I've already tried to create a simple button and display an UIViewController as a popup of one another but don't know how to do what Google+ app (and other ones) do, instead.

UPDATE

Here's the screenshots.

As you can see when you tap into a post, the post slides up and became a new contained UIViewController.


回答1:


As has been pointed out, there are tons of ways to achieve this UI, but one way is to grab the view out of the tableview cell, move it onto some new backdrop, and change its frame. And when you're putting it back, just reverse the process.

In a little more detail that might be as follows:

  1. In the cell, I have a container view which is a scroll view (whose user interaction is usually disabled).

  2. When user taps on it,

    • Create a new backdrop view that is transparent that occupies the whole screen;

    • Give that backdrop a tap gesture recognizer that can reverse the process at a later point;

    • Move the cell's container view from the cell to this new backdrop view (using convertRect so it doesn't move yet);

    • Animate the slight shrinking of the container via transformation (a subtle effect which gives you the effect of having "pushed down" on the view);

    • In the completion block of that animation, initiate a new animation that:

      • Restores the transformation back to identity;

      • Sets the backdrop background color to a largely opaque (but not entirely so) color;

      • Animate the size of the container view to take up more of the screen

      • Go ahead and enable user interaction on that container view so you can scroll around;

  3. Have a handler for the tap gesture on our backdrop that reverses that process.

Thus:

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    PostCell *cell = (id)[tableView cellForRowAtIndexPath:indexPath];

    // create subview to obscure the table view behind us

    UIView *backdropView = [[UIView alloc] initWithFrame:self.view.bounds];
    backdropView.backgroundColor = [UIColor clearColor];
    [self.view addSubview:backdropView];
    self.backdropView = backdropView;

    // add a tap gesture so we can reverse the process

    [backdropView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
                                                                              action:@selector(handleTapGesture:)]];

    // move the cell's container view to the backdrop view, preserving its location on the screen
    // (so it doesn't look like it moved)

    self.viewToMove = cell.containerView;
    self.viewToMoveOriginalCell = cell;
    self.viewToMoveOriginalFrame = cell.containerView.frame;

    // figure out where this goes on the backdrop

    CGRect frame = [self.viewToMoveOriginalCell convertRect:self.viewToMoveOriginalFrame
                                                     toView:self.backdropView];

    // move it there (though it won't appear to move yet, we're just changing its superview)

    [self.backdropView addSubview:self.viewToMove];
    self.viewToMove.frame = frame;

    // now do the animation

    [UIView animateWithDuration:0.25
                          delay:0.0
                        options:0.0
                     animations:^{

                         // first shrinking it a bit

                         self.viewToMove.transform = CGAffineTransformMakeScale(0.95, 0.95);
                     }
                     completion:^(BOOL finished) {

                         // finally restoring the size and making it bigger
                         // (and reveal the backdrop that obscures the tableview)

                         [UIView animateWithDuration:0.5 animations:^{
                             CGFloat horizontalMargin = (self.view.bounds.size.width - frame.size.width) / 2.0;
                             backdropView.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8];
                             self.viewToMove.transform = CGAffineTransformIdentity;
                             self.viewToMove.frame = CGRectMake(horizontalMargin, kVerticalMargin, self.view.bounds.size.width - 2.0 * horizontalMargin, self.view.bounds.size.height - 2.0 * kVerticalMargin);
                         }];

                         self.viewToMove.userInteractionEnabled = YES;
                     }];
}

- (void)handleTapGesture:(UITapGestureRecognizer *)gesture
{
    [UIView animateWithDuration:0.5
                          delay:0.0
                        options:0
                     animations:^{

                         // in case user scrolled in content view, scroll back

                         [self.viewToMove setContentOffset:CGPointZero animated:YES];

                         // figure out where to resize view on container view so it's
                         // going to end up where it will end up in the cell

                         CGRect frame = [self.viewToMoveOriginalCell convertRect:self.viewToMoveOriginalFrame
                                                                          toView:self.backdropView];
                         self.viewToMove.frame = frame;

                         // make the back drop appear to gracefully disappear

                         self.backdropView.backgroundColor = [UIColor clearColor];

                         // shrink content view a tad in the process

                         self.viewToMove.transform = CGAffineTransformMakeScale(0.95, 0.95);
                     }
                     completion:^(BOOL finished) {

                         // when done with that animation ...

                         [UIView animateWithDuration:0.25
                                               delay:0.0
                                             options:0
                                          animations:^{

                                              // restore the size of the content view

                                              self.viewToMove.transform = CGAffineTransformIdentity;
                                          }
                                          completion:^(BOOL finished) {

                                              // when all done, put the content view back
                                              // in the cell

                                              [self.viewToMoveOriginalCell addSubview:self.viewToMove];
                                              self.viewToMove.frame = self.viewToMoveOriginalFrame;

                                              // turn off its user interaction again 

                                              self.viewToMove.userInteractionEnabled = NO;

                                              // and now safely discard the backdrop

                                              [self.backdropView removeFromSuperview];
                                          }];
                    }];
}

As you can tell, this is all standard table views and the like. If you wanted to use view controller containment (e.g. if the view had significant user interaction), you could do that, too. It doesn't affect the UX in terms of the growing/shrinking of the cell's container view.

Also, this all is non-autolayout. You could do this with auto layout, but is more of a hassle, IMHO, because you'd probably have to remove and add constraints, but certainly can be done.



来源:https://stackoverflow.com/questions/16989516/uiviewcontroller-containment-with-animation-like-google

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!