4

我嘗試模擬Line Messenger應用程序(日本的事實上的Messenger軟件)中存在的行爲。iOS - 在關閉和滾動手勢之間切換

基本上,他們有一個內置滾動視圖的模式視圖控制器。當滾動操作到達其內容的頂部時,視圖控制器將無縫切換到交互式解除動畫。另外,當手勢將視圖返回到屏幕頂部時,控件將返回到滾動視圖。

下面是它的外觀。

demo gif

對於我的生活,我想不通他們怎麼做。我嘗試了幾種不同的方法,但都失敗了,我沒有想法。任何人都可以將我指向正確的方向嗎?

EDIT2

爲了澄清,我想模仿不只是簡單地拖動窗口下的行爲。我可以那樣做,沒問題。

我想知道同一個滾動手勢(不用提起手指)如何觸發解除轉換,然後在視圖被拖回到原始位置後將控制轉移回滾動視圖。

這是我無法弄清楚的部分。

末EDIT2

EDIT1

這裏是我到目前爲止所。我能夠使用滾動視圖委託方法來添加處理常規解僱動畫的目標選擇器,但它仍然無法按預期工作。

我創建了一個UIViewController作爲一個屬性UIWebView。然後我把它放在一個UINavigationController,這是模態地呈現。

導航控制器使用動畫/轉換控制器進行定期交互式解除(可以通過在導航欄上進行手勢操作來完成)。

從這裏,一切工作正常,但解僱不能從滾動視圖觸發。

NavigationController.h

@interface NavigationController : UINavigationController <UIViewControllerTransitioningDelegate> 

@property (nonatomic, strong) UIPanGestureRecognizer *gestureRecog; 

- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer; 

@end 

NavigationController.m

#import "NavigationController.h" 
#import "AnimationController.h" 
#import "TransitionController.h" 

@implementation NavigationController { 
    AnimationController *_animator; 
    TransitionController *_interactor; 
} 

- (instancetype)init { 
    self = [super init]; 

    self.transitioningDelegate = self; 

    _animator = [[AnimationController alloc] init]; 
    _interactor = [[TransitionController alloc] init]; 

    return self; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    // Set the gesture recognizer 
    self.gestureRecog = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)]; 
    [self.view addGestureRecognizer:_gestureRecog]; 
} 

- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator { 
    if (animator == _animator && _interactor.hasStarted) { 
     return _interactor; 
    } 
    return nil; 
} 

- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { 
    if (dismissed == self || [self.viewControllers indexOfObject:dismissed] != NSNotFound) { 
     return _animator; 
    } 
    return nil; 
} 

- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecog { 
    CGFloat threshold = 0.3f; 

    CGPoint translation = [gestureRecog translationInView:self.view]; 
    CGFloat verticalMovement = translation.y/self.view.bounds.size.height; 
    CGFloat downwardMovement = fmaxf(verticalMovement, 0.0f); 
    CGFloat downwardMovementPercent = fminf(downwardMovement, 1.0f); 

    switch (gestureRecog.state) { 
     case UIGestureRecognizerStateBegan: { 
      _interactor.hasStarted = YES; 
      [self dismissViewControllerAnimated:YES completion:nil]; 
      break; 
     } 
     case UIGestureRecognizerStateChanged: { 
      if (!_interactor.hasStarted) { 
       _interactor.hasStarted = YES; 
       [self dismissViewControllerAnimated:YES completion:nil]; 
      } 
      _interactor.shouldFinish = downwardMovementPercent > threshold; 
      [_interactor updateInteractiveTransition:downwardMovementPercent]; 
      break; 
     } 
     case UIGestureRecognizerStateCancelled: { 
      _interactor.hasStarted = NO; 
      [_interactor cancelInteractiveTransition]; 
      break; 
     } 
     case UIGestureRecognizerStateEnded: { 
      _interactor.hasStarted = NO; 
      if (_interactor.shouldFinish) { 
       [_interactor finishInteractiveTransition]; 
      } else { 
       [_interactor cancelInteractiveTransition]; 
      } 
      break; 
     } 
     default: { 
      break; 
     } 
    } 
} 

@end 

現在,我必須讓手勢操作時滾動視圖已經達到了頂級觸發。所以,這是我在視圖控制器中所做的。

WebViewController.m

#import "WebViewController.h" 
#import "NavigationController.h" 

@interface WebViewController() 

@property (weak, nonatomic) IBOutlet UIWebView *webView; 
@end 

@implementation WebViewController { 
    BOOL _isHandlingPan; 
    CGPoint _topContentOffset; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self.webView.scrollView setDelegate:self]; 
}  

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 
    if ((scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan || 
     scrollView.panGestureRecognizer.state == UIGestureRecognizerStateChanged) && 
     ! _isHandlingPan && 
     scrollView.contentOffset.y < self.navigationController.navigationBar.translucent ? -64.0f : 0) { 

     NSLog(@"Adding scroll target"); 

     _topContentOffset = CGPointMake(scrollView.contentOffset.x, self.navigationController.navigationBar.translucent ? -64.0f : 0); 
     _isHandlingPan = YES; 
     [scrollView.panGestureRecognizer addTarget:self action:@selector(handleGesture:)]; 
    } 
} 
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 
    NSLog(@"Did End Dragging"); 
    if (_isHandlingPan) { 
     NSLog(@"Removing action"); 
     _isHandlingPan = NO; 
     [scrollView.panGestureRecognizer removeTarget:self action:@selector(handleGesture:)]; 
    } 
} 
- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer { 
    [(NavigationController*)self.navigationController handleGesture:gestureRecognizer]; 
} 

這仍然無法正常工作完全正確。即使在解散動畫期間,滾動視圖仍然隨着手勢滾動。

末EDIT1

+1

你需要達成的滾動偏移值增加transitionViewController動畫ZFDragableModalTransition

圖像的源代碼。查看視圖控制器轉換的示例。 – iAviator

回答

2

這是一個自定義的互動轉變。

首先,你需要設置的UIViewController

id<UIViewControllerTransitioningDelegate> transitioningDelegate; 

transitioningDelegate然後當拖動到頂部,你開始轉換implment這兩種方法

//Asks your delegate for the transition animator object to use when dismissing a view controller. 
- animationControllerForDismissedController: 
//Asks your delegate for the interactive animator object to use when dismissing a view controller. 
- interactionControllerForDismissal: 

,你可以使用UIPercentDrivenInteractiveTransition控制進度在滾動。

您也可以參考ZFDragableModalTransition

+0

我用我的代碼編輯了我的帖子,使我獲得了最大的成功。我猜我在正確的軌道上?或者我的方法有缺陷? – ABeard89

+0

我想我只是通過源代碼來看看我的遺漏是什麼。 – ABeard89

+0

CocoaPod沒有做我想做的一件事。這就是我目前陷入困境的地方。我想要相同的滾動手勢(不需要擡起手指)觸發解除轉換,並且在視圖被拖回到原始位置後,我希望滾動視圖重新獲得控制權。這是我無法弄清楚的部分。 – ABeard89