UIViewController包含像Google+这样的动画

时间:2013-06-07 17:10:25

标签: iphone ios cocoa-touch uiviewcontroller core-animation

了解我要解释的内容的最佳方式是打开 Google + 应用,然后点按主要帖子中显示的帖子的背景中的任意位置。

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

我认为这是一个常见的UIViewController遏制场景,其中一个UIViewController位于另一个内。但是帖子如何能够动态地移动它并在包含的视图控制器中“转移”它自己?

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

更新

这是截图。

enter image description here enter image description here

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

1 个答案:

答案 0 :(得分:2)

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

稍微详细一点,可能如下:

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

  2. 当用户点击它时,

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

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

    • 将单元格的容器视图从单元格移动到此新背景视图(使用convertRect,因此它尚未移动);

    • 通过转换动画轻微收缩容器(一种微妙的效果,可以让你在视图中按下#34;#/ p>

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

      • 将转换恢复为标识;

      • 将背景幕背景颜色设置为很大程度上不透明(但并非完全如此)的颜色;

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

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

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

  4. 因此:

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

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

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