2

理解我要解释的内容的最佳方法是打开Google+应用程序,然后点击帖子主流中显示的帖子背景中的任意位置。

当您点击它时,整个帖子会以漂亮的动画在屏幕中央移动,并在其下方加载帖子的评论。

我认为这是一种常见的UIViewController收容方案,其中一个UIViewController在另一个内部。但是帖子如何以动画方式移动它并在包含的视图控制器内“转移”自身?

我已经尝试创建一个简单的按钮并将一个按钮显示UIViewController为彼此的弹出窗口,但不知道如何执行 Google+ 应用程序(和其他应用程序)的操作。

更新

这是屏幕截图。

在此处输入图像描述 在此处输入图像描述

正如您在点击帖子时看到的那样,帖子向上滑动并成为新的包含UIViewController.

4

1 回答 1

2

正如已经指出的,有很多方法可以实现这个 UI,但一种方法是从 tableview 单元格中获取视图,将其移动到一些新的背景上,然后更改它的框架。当你把它放回去时,只需反转这个过程。

更详细一点,可能如下:

  1. 在单元格中,我有一个容器视图,它是一个滚动视图(其用户交互通常被禁用)。

  2. 当用户点击它时,

    • 创建一个占据整个屏幕的透明背景视图;

    • 为该背景提供一个轻击手势识别器,该识别器可以在以后反转该过程;

    • 将单元格的容器视图从单元格移动到这个新的背景视图(使用convertRect所以它还没有移动);

    • 通过变换对容器的轻微收缩进行动画处理(一种微妙的效果,让您有“下推”视图的效果);

    • 在该动画的完成块中,启动一个新动画:

      • 将转换恢复为身份;

      • 将背景背景颜色设置为大部分不透明(但不完全如此)的颜色;

      • 动画容器视图的大小以占用更多屏幕

      • 继续并在该容器视图上启用用户交互,以便您可以滚动;

  3. 在我们的背景上为点击手势设置一个处理程序,以反转该过程。

因此:

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

如您所知,这是所有标准表格视图等。如果您想使用视图控制器包含(例如,如果视图具有重要的用户交互),您也可以这样做。就单元格的容器视图的增长/缩小而言,它不会影响用户体验。

此外,这一切都是非自动布局。您可以使用自动布局来做到这一点,但更麻烦的是,恕我直言,因为您可能必须删除和添加约束,但肯定可以做到。

于 2013-06-07T23:25:09.880 回答