iOS-在关闭和滚动手势之间切换

iOS-在关闭和滚动手势之间切换,ios,uiscrollview,uigesturerecognizer,modalviewcontroller,Ios,Uiscrollview,Uigesturerecognizer,Modalviewcontroller,我正试图模仿Line messenger应用程序(日本事实上的messenger应用程序)中的一种行为 基本上,他们有一个模态视图控制器,里面有一个滚动视图。当滚动动作到达其内容的顶部时,视图控制器将无缝切换到交互式动画。此外,当手势将视图返回到屏幕顶部时,控制将返回到滚动视图 这是它的gif图像 就我个人而言,我不知道他们是怎么做到的。我试过几种不同的方法,但都失败了,我也没有主意了。谁能给我指出正确的方向吗 EDIT2 要澄清的是,我想要模仿的行为不仅仅是将窗口向下拖动。我能做到,没问题

我正试图模仿Line messenger应用程序(日本事实上的messenger应用程序)中的一种行为

基本上,他们有一个模态视图控制器,里面有一个滚动视图。当滚动动作到达其内容的顶部时,视图控制器将无缝切换到交互式动画。此外,当手势将视图返回到屏幕顶部时,控制将返回到滚动视图

这是它的gif图像

就我个人而言,我不知道他们是怎么做到的。我试过几种不同的方法,但都失败了,我也没有主意了。谁能给我指出正确的方向吗

EDIT2

要澄清的是,我想要模仿的行为不仅仅是将窗口向下拖动。我能做到,没问题

我想知道相同的滚动手势(不抬起手指)是如何触发切换的,然后在视图被拖回原始位置后将控制权转移回滚动视图

这是我无法理解的部分

结束编辑2

EDIT1

这是我到目前为止所拥有的。我能够使用scroll view delegate方法添加一个处理常规动画的目标选择器,但它仍然不能按预期工作

我使用
UIWebView
作为属性创建了一个
UIViewController
。然后我把它放在一个
UINavigationController
中,它以模态的形式呈现

导航控制器使用动画/过渡控制器进行常规交互(可以通过在导航栏上做手势来完成)

从这里开始,一切正常,但不能从滚动视图触发解雇

导航控制器

@interface NavigationController : UINavigationController <UIViewControllerTransitioningDelegate>

@property (nonatomic, strong) UIPanGestureRecognizer *gestureRecog;

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

@end
@界面导航控制器:UINavigationController
@属性(非原子,强)UIPangestureRecognitor*gestureRecog;
-(无效)手势识别器:(UIPangestureRecognitor*)手势识别器;
@结束
导航控制器

#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
#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];
}
#导入“NavigationController.h”
#导入“AnimationController.h”
#导入“TransitionController.h”
@实现导航控制器{
AnimationController*\u animator;
TransitionController*\u交互器;
}
-(instancetype)初始化{
self=[super init];
self.transitioningDelegate=self;
_animator=[[AnimationController alloc]init];
_interactor=[[TransitionController alloc]init];
回归自我;
}
-(无效)viewDidLoad{
[超级视图下载];
//设置手势识别器
self.gestureRecog=[[UIPangestureRecognitizer alloc]initWithTarget:self action:@selector(HandleTesture:)];
[self.view addgestureRecognitor:\u gestureRecog];
}
-(id)InteractionControllerFordisessal:(id)动画师{
if(animator==\u animator&&u interactitor.hasStarted){
返回交互器;
}
返回零;
}
-(id)animationControllerForDismissedController:(UIViewController*)已解除{
if(discomered==self | |[self.viewControllers indexOfObject:discomered]!=NSNotFound){
返回动画;
}
返回零;
}
-(无效)手势测试:(UIPangestureRecognitor*)手势记录{
CGFloat阈值=0.3f;
CGPoint translation=[gestureRecog translationview:self.view];
CGFloat verticalMovement=translation.y/self.view.bounds.size.height;
CGFloat向下移动=fmaxf(垂直移动,0.0f);
CGFloat向下移动百分比=fminf(向下移动,1.0f);
开关(手势记录状态){
案例UIgestureRecognitzerStateStart:{
_interactior.hasStarted=是;
[自我解除视图控制器激活:是完成:无];
打破
}
案例UIgestureRecognitzerStateChanged:{
if(!\u interactior.hasStarted){
_interactior.hasStarted=是;
[自我解除视图控制器激活:是完成:无];
}
_interactor.shouldFinish=向下移动百分比>阈值;
[\u Interactitor updateInteractiveTransition:downwardMovementPercent];
打破
}
案例UIgestureRecognitizerState已取消:{
_interactior.hasStarted=否;
[\u Interactior cancelInteractiveTransition];
打破
}
案例UIgestureRecognitzerStateEnded:{
_interactior.hasStarted=否;
if(_interactior.shouldFinish){
[_交互者完成交互转换];
}否则{
[\u Interactior cancelInteractiveTransition];
}
打破
}
默认值:{
打破
}
}
}
@结束
现在,我必须在滚动视图到达顶部时触发手势处理。下面是我在视图控制器中所做的

WebViewController.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
#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];
}
#导入“WebViewController.h”
#导入“NavigationController.h”
@接口WebViewController()
@属性(弱、非原子)ibuiwebview*webView;
@结束
@WebViewController的实现{
波尔·伊山灵潘;
CGPoint _topContentOffset;
}
-(无效)viewDidLoad{
[超级视图下载];
[self.webView.scrollView setDelegate:self];
}    
-(无效)scrollViewDidScroll:(UIScrollView*)scrollView{
如果((scrollView.panGestureRecognizer.state==UIgestureRecognizerStateStart||
scrollView.panGestureRecognizer.state==UIGestureRecognizerStateChanged)&&
!\u isHandlingPan&&
scrollView.contentOffset.yfunc shouldHandlePanelInteractionGesture() -> Bool {
    return (scrollView.contentOffset.y == 0);
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.bounces = (scrollView.contentOffset.y > 10);
}
ScrollViewController.transitioningDelegate = self.panelTransitioningDelegate
ScrollViewController.modalPresentationStyle = .custom