【问题标题】:How to replicate Messages bouncing bubbles in iOS 7如何在 iOS 7 中复制弹跳气泡的消息
【发布时间】:2013-11-05 17:32:57
【问题描述】:

当您在 iOS 7 中的消息应用程序中进行对话时,如果您向上或向下滚动,您会注意到气泡以及更多说明消息发送时间的文字会弹回原位。

我正在尝试在我自己的表格视图中复制它,但没有找到方法。

我假设它使用的是 UIDynamics,但我不确定如何将其与滚动和内容弹跳联系起来。

任何帮助将不胜感激

【问题讨论】:

  • 我有答案,谷歌 BPXLFlowLayout by Brandon Alexander, Black Pixel。他的类 BPXLFlowLayout 非常接近 Messages 中物理的确切感觉。
  • 顺便说一句,当您使用这些东西时,不要忘记这个重要的相关提示:stackoverflow.com/a/23926712/294884
  • 为了完全清楚,基本答案是“你使用 UICollectionViewFlowLayout”。正如我上面提到的,BPXLFlowLayout 是 BPXLFlowLayout 的一个了不起的版本,它可以完美地满足您的需求。

标签: ios ios7 uikit-dynamics


【解决方案1】:

如果您想自己复制该效果,则需要 UIKit Dynamics。 我本人对这种效果很感兴趣,并在今年的 WWDC 上对此进行了解释。

看看 WWDC Session 217: Exploring Scroll Views on iOS 7

网上也有阅读使用组件,如THSpringyCollectionView

【讨论】:

    【解决方案2】:

    我也对这种效果很感兴趣,在我对网络的研究过程中,我发现了这个教程 - http://www.objc.io/issue-5/collection-views-and-uidynamics.html 它正在实现相同的想法。

    【讨论】:

    • 我发现本教程(以及 WWDC 会议上的演示)没有复制 Messages 应用程序的行为。在消息应用程序中,没有振荡,一切都很顺利。在演示应用程序中,即使您的阻尼比 ≥ 1(这在物理上没有意义),也会存在残余振荡。
    • @KPM 尝试给弹簧附件行为一些长度(如 1.0f)。
    • 是的,BPXLFlowLayout 是基于该教程,而 Brandon 已经完成了所有复制 Messages 应用程序物理特性的艰苦工作!干杯
    • @JoeBlow BPXLFlowLayout 不会重现 Message 的物理特性。有太多的振荡和边界。
    • @ChaseS 在该块内,我将查看弹簧锚点和项目点之间的增量(称为变量“d”)。如果 d 小于 1.0,我会简单地应用一个非常大的阻尼因子,例如 2000.0(这样它会立即稳定下来)。否则,我将使用二次函数(例如 [Constant] * d^2 + [Another constant])确定阻尼因子。我通过实验选择了 [Constant] 和 [Another constant]。最后,我还使用了行为的频率,为较小的 d 值选择了稍高的频率。祝你好运!
    【解决方案3】:

    您可以像这样为滚动视图中的内容添加弹性反弹:

    1. 设置 UIScrollview 并添加到您的视图中。

      mainScroller = [UIScrollView new];
      mainScroller.frame = CGRectMake(0, 0, w, h);
      mainScroller.bounces = true;
      mainScroller.pagingEnabled = false;
      mainScroller.delegate = self;
      [self.view addSubview:mainScroller];
      
    2. 布局 UIView 并将其添加到您的滚动视图中。

      contentView = [UIView new];
      contentView.frame = CGRectZero;
      [mainScroller addSubview:contentView];
      
    3. 为您的“contentView”添加子视图。

      UIView * unitView = [UIView new];
      unitView.frame = CGRectMake(0, yOff, w, 280);
      [contentView addSubview:unitView]; 
      
    4. 调整 contentView 和 scrollview 的大小以适应内容。 w 下方是视图宽度,yOff 是内容的总累积高度。

      contentView.frame = CGRectMake(0, 0, w, yOff);
      mainScroller.contentSize = CGSizeMake(w, yOff);
      
    5. 在您的 scrollViewDidScroll 方法中,添加以下代码:

       float y = mainScroller.contentOffset.y;
       contentView.transform = CGAffineTransformMakeTranslation(0, y);
      
       for (UIView * sub in contentView.subviews){
           int index = (int)[contentView.subviews indexOfObject:sub];
           float delay = index * 0.03;
           float duration = 1.0f - delay;
      
           [UIView animateWithDuration:duration
                                 delay:delay
                usingSpringWithDamping:0.8
                 initialSpringVelocity:0.7
                               options:UIViewAnimationOptionCurveEaseInOut| UIViewAnimationOptionAllowUserInteraction
                            animations:^{
                                sub.transform = CGAffineTransformMakeTranslation(0, -y);
                           }
                       completion:^(BOOL finished){
                       }]; 
       }
      

    UIViewAnimationOptionAllowUserInteraction 动画选项允许您立即与内容进行交互。调整延迟、持续时间、弹簧阻尼和弹簧速度变量以满足您的需求。

    代码可以进一步调整以允许触摸检测;就目前而言,弹性反弹起源于 scrollView 的顶部并向下穿过视图,这对于较短的 scrollViews 几乎不明显。

    编辑:触摸检测

    如果您想允许触摸检测,请在您的 scrollViewDidScroll 方法中替换为这些行:

    int index = (int)[contentView.subviews indexOfObject:sub];
    int deviation = abs(touchIndex - index);
    float delay = deviation * 0.03;
    float duration = 1.0f - delay;
    

    新变量 touchIndex 的定义如下:

    -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    
        //grab the location of the touch event
        CGPoint location = [scrollView.panGestureRecognizer locationInView:scrollView];
        int yTouch = location.y; //grab y coordinate
        touchIndex = (yTouch - 100) / 100; //calculate the index of the cell, where 100 is the height of the cell
    
    }
    

    如果您有动态单元格高度,请将它们存储在数组中,例如'选定的高度'。然后更新下面的 scrollViewWillBeginDragging 方法,其中“tally”浮动设置为 70 以允许标题。

    -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    
        //grab the location of the touch event
        CGPoint location = [scrollView.panGestureRecognizer locationInView:scrollView];
        int yTouch = location.y; //grab y coordinate
        float tally = 70.0f;
        for (int n = 0; n < selectedHeights.count; n++){
            float cellHeight = [selectedHeights[n] floatValue];
            tally += cellHeight;
            if (tally > yTouch){
                touchIndex = n;
                break;
            }
        }
    }
    

    【讨论】:

    • 你能解释一下我是怎么用tableview做的吗..我只需要弹跳动画。
    • 我想有一种方法可以使用 tableview,或者肯定是具有自定义流布局的 uicollectionview,您可以在其中跟踪单元格的位置重新作为超级视图,但我不知道,有人否则可能吗?如果您担心在大量单元格上出队,我可以为此发布一些代码。整个事情并没有比 Apple 所需的 tableview 方法多多少行,当你开始添加动态背景(如消息应用程序蓝色渐变)时,它是有意义的。
    • 嗨@JohnnyRockex,你能把你的代码放在演示中吗?就像你的 gif 显示一样?会更有价值。谢谢
    • @JohnnyRockex 您能否解释一下表格视图或请提供示例代码
    • @SaikumarReddy 嗨 Sai,我已经有一段时间没有编写此代码了,但看起来它没有使用 UITableView。我现在的猜测是使用 tableView 或 UICollectionView,并挂钩到 scrollViewDidScroll 方法中的函数,然后从那里进行操作。祝你好运。
    猜你喜欢
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多