How to replicate Messages bouncing bubbles in iOS 7

非 Y 不嫁゛ 提交于 2019-11-28 18:54:10

If you want to replicate that effect yourself, you need UIKit Dynamics. I was interested in that effect myself and it was explained at WWDC this year.

Take a look at WWDC Session 217: Exploring Scroll Views on iOS 7

There are also read to use components on the internet, such as THSpringyCollectionView

I was interested in that effect also and during my research on the web I found this tutorial - http://www.objc.io/issue-5/collection-views-and-uidynamics.html It is implementing the same idea.

You can add a springy bounce to content in your scrollview like this:

  1. Set up a UIScrollview and add to your view.

    mainScroller = [UIScrollView new];
    mainScroller.frame = CGRectMake(0, 0, w, h);
    mainScroller.bounces = true;
    mainScroller.pagingEnabled = false;
    mainScroller.delegate = self;
    [self.view addSubview:mainScroller];
    
  2. Layout a UIView and add it within your scrollview.

    contentView = [UIView new];
    contentView.frame = CGRectZero;
    [mainScroller addSubview:contentView];
    
  3. Add subviews your your 'contentView'.

    UIView * unitView = [UIView new];
    unitView.frame = CGRectMake(0, yOff, w, 280);
    [contentView addSubview:unitView]; 
    
  4. Resize both contentView and scrollview to fit the content. Below w is view width and yOff the total cumulative height of the content.

    contentView.frame = CGRectMake(0, 0, w, yOff);
    mainScroller.contentSize = CGSizeMake(w, yOff);
    
  5. In your scrollViewDidScroll method, add the following code:

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

The UIViewAnimationOptionAllowUserInteraction animation option allows for you to interact with the content immediately. Tweak the delay, duration, spring dampening and spring velocity variables to suit your needs.

The code could be further adapted to allow for touch detection; as it stands, the springy bounce originates at the top of the scrollView and descends down through the views, which for shorter scrollViews is barely noticeable.

EDIT: Touch detection

If you want to allow for touch detection, replace with these lines in your scrollViewDidScroll method:

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

Where the new variable touchIndex is defined like so:

-(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

}

If you have dynamic cell heights, store them in an array e.g. 'selectedHeights'. Then update your scrollViewWillBeginDragging method for the below, where the 'tally' float is set to 70 to allow for a header.

-(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;
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!