草庐IT

iphone - UIViewController 包含动画,如 Google+

coder 2024-01-20 原文

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

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

我认为这是一个常见的 UIViewController 包含场景,其中一个 UIViewController 在另一个里面。但是帖子如何动态地移动它并在包含的 View Controller 中“转移”自己呢?

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

更新

这是屏幕截图。

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

最佳答案

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

更详细一点,可能如下:

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

  2. 当用户点击它时,

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

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

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

    • 通过转换为容器的轻微收缩设置动画(一种微妙的效果,让您产生在 View 上“下推”的效果);

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

      • 恢复身份转换;

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

      • 动画显示容器 View 的大小以占据更多屏​​幕

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

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

如您所知,这都是标准的表格 View 等。如果你想使用 View Controller 包含(例如,如果 View 有重要的用户交互),你也可以这样做。它不会影响单元格容器 View 的增大/缩小方面的用户体验。

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

关于iphone - UIViewController 包含动画,如 Google+,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16989516/

有关iphone - UIViewController 包含动画,如 Google+的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby-on-rails - 使用包含多个关联和单独的条件 - 2

    我的Gallery模型中有以下查询:media_items.includes(:photo,:video).rank(:position_in_gallery)我的图库模型有_许多媒体项,每个都有一个照片或视频关联。到目前为止,一切正常。它返回所有media_items包括它们的photo或video关联,由media_item的position_in_gallery属性排序。但是我现在需要将此查询返回的照片限制为仅具有is_processing属性的照片,即nil。是否可以进行相同的查询,但条件是返回的照片等同于:.where(photo:'photo.is_processingIS

  8. ruby - 我怎样才能只写一次 "Text"并同时检查 path_info 是否包含 'A' ? - 2

    -if!request.path_info.include?'A'%{:id=>'A'}"Text"-else"Text"“文本”写了两次。我怎样才能只写一次并同时检查path_info是否包含“A”? 最佳答案 有两种方法可以做到这一点。使用部分,或使用content_forblock:如果“文本”较长,或者是一个重要的子树,您可以将其提取到一个部分。这会使您的代码变干一点。在给出的示例中,这似乎有点矫枉过正。在这种情况下更好的方法是使用content_forblock,如下所示:-if!request.path_info.inc

  9. Ruby,使用包含 TK GUI 的 ocra 部署一个 exe - 2

    Ocra无法处理需要“tk”的应用程序require'tk'puts'nope'用奥克拉http://github.com/larsch/ocra不起作用(如链接中的一个问题所述)问题:https://github.com/larsch/ocra/issues/29(Ocra是1.9的"new"rubyscript2exe,本质上它用于将rb脚本部署为可执行文件)唯一的问题似乎是缺少tcl的DLL文件我不认为这是一个问题据我所知,问题是缺少tk的DLL文件如果它们是已知的,则可以在执行ocra时将它们包括在内有没有办法知道tk工作所需的DLL依赖项? 最佳答

  10. ruby - 允许主机名包含下划线的 URI.parse 的替代方法 - 2

    我正在使用DMOZ的listofurltopics,其中包含一些具有包含下划线的主机名的url。例如:608609TheOuterHeaven610InformationandimagegalleryofMcFarlane'sactionfiguresforTrigun,Akira,TenchiMuyoandotherJapaneseSci-Fianimations.611Top/Arts/Animation/Anime/Collectibles/Models_and_Figures/Action_Figures612虽然此url可以在网络浏览器中使用(或者至少在我的浏览器中可以使用:

随机推荐