UIViewController遏制与动画像Google+ [英] UIViewController Containment with animation like Google+

查看:98
本文介绍了UIViewController遏制与动画像Google+的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

了解我要解释的最好方法是开启 Google + 应用程式,然后轻按主要讯息串中显示的讯息背景中的任何地方。



当你点击它,整个帖子移动自己在屏幕的中心有一个漂亮的动画,它加载帖子的评论下面它。



我认为这是一个常见的 UIViewController 遏制场景,其中一个 UIViewController 在另一个。但是如何post可以移动它,并在所包含的视图控制器中传输自己?



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



UPDATE



这是屏幕截图。






正如你可以看到,当你点击一个帖子,帖子滑了起来,成为一个新的包含 UIViewController

解决方案

正如已经指出的,有很多种方法来实现这个UI,一种方法是从tableview单元格抓取视图,将其移动到一些新的背景,并更改其框架。当你把它放回来,只是逆转过程。



更多细节可能如下:



  1. 当用户点击它时,会显示一个容器视图,其中的用户交互通常是禁用的。 p>


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


    • 将此背景幕设为可以在稍后的某一点上逆转此过程的点按手势识别器;


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


    • 通过转换(一个微妙的效果,给你的效果是下压的视图);


    • 在该动画的完成块,发起一个新动画:




      • 将转换还原为身份;


      • 将背景幕背景颜色设置为基本不透明(但不完全是)颜色;


      • 占用更多的屏幕


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




  2. 在我们的背景幕上点击手势的处理程序, >


因此:

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

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

//创建子视图以隐藏我们后面的表视图

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

//添加一个敲击手势,以便我们可以逆转过程

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

//将单元格的容器视图移动到背景视图,保留其在屏幕上的位置
//(所以它看起来不像移动)

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

//找出这在背景上的位置

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

//移动它(虽然它不会移动,我们只是改变它的superview)

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

//现在做动画

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

//首先缩小它一点

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

//最后还原大小并使其更大
//(并显示遮蔽tableview的背景)

[UIView animateWithDuration:0.5 animations:^ {
CGFloat horizo​​ntalMargin =(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(horizo​​ntalMargin,kVerticalMargin,self.view.bounds.size.width - 2.0 * horizo​​ntalMargin,self.view.bounds.size.height - 2.0 * kVerticalMargin);
}];

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

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

//如果用户在内容视图中滚动,向后滚动

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

//找出在容器视图上调整视图大小的位置
//最终到达单元格中的最后位置

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

//使后退显示为优雅地消失

self.backdropView.backgroundColor = [UIColor clearColor];

//在进程中收缩内容视图一个tad

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

//当动画完成时...

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

//恢复内容视图的大小

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

//完成后,将内容视图返回
//在单元格中

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

//再次关闭其用户交互

self.viewToMove.userInteractionEnabled = NO;

//现在安全地丢弃背景

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

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



此外,这一切都是非自动布局。你可以使用自动布局,但是更多的麻烦,IMHO,因为你可能必须删除和添加约束,但一定可以做。


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.

解决方案

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.

这篇关于UIViewController遏制与动画像Google+的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆