gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 03:58:46 24 4
gpt4 key购买 nike

我正在尝试模仿 Line Messenger 应用程序(日本事实上的 Messenger 应用程序)中的一种行为。

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

这是它的外观的 gif。

demo gif

对于我的生活,我无法弄清楚他们是如何做到的。我尝试了几种不同的方法,但都失败了,而且我没有想法。谁能指出我正确的方向?

EDIT2

澄清一下,我要模拟的行为不仅仅是向下拖动窗口。我可以做到,没问题。

我想知道相同的滚动手势(不抬起手指)如何触发关闭过渡,然后在 View 被拖回原始位置后将控制权转移回 ScrollView 。

这是我想不通的部分。

结束EDIT2

编辑1

这是我目前所拥有的。我能够使用 ScrollView 委托(delegate)方法来添加处理常规关闭动画的目标选择器,但它仍然无法按预期工作。

我创建一个 UIViewController 并将 UIWebView 作为属性。然后,我将其放入模态呈现的 UINavigationController 中。

导航 Controller 使用动画/过渡 Controller 进行常规交互式解雇(这可以通过在导航栏上打手势来完成)。

从这里开始,一切正常,但无法从 ScrollView 触发解雇。

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

现在,我必须让手势处理在 ScrollView 到达顶部时触发。所以,这就是我在 View Controller 中所做的。

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

这仍然不能正常工作。即使在关闭动画期间, ScrollView 仍会随着手势滚动。

结束EDIT1

最佳答案

这是一个自定义的交互式过渡。

首先,你需要设置UIViewControllertransitioningDelegate

id<UIViewControllerTransitioningDelegate> transitioningDelegate;

然后实现这两个方法

 //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的源码

ZFDragableModalTransition 的图像

关于iOS - 在关闭和滚动手势之间切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43014381/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com