che*_*etu 17 iphone objective-c uigesturerecognizer ios
我想在屏幕上向右滑动时弹出一个视图,或者它像导航栏的后退按钮一样工作.
我在用:
self.navigationController.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)self;
Run Code Online (Sandbox Code Playgroud)
这个单行代码用于流行导航视图,它对我来说很有用,但是当我在屏幕中间滑动时,这将无法像Instagram iPhone应用程序那样工作.
在这里,我给出了一个Instagram应用程序的屏幕,你可以看到滑动右侧弹出导航视图的示例:

rdu*_*and 13
Apple自动实现"刷卡直播VC"仅适用于屏幕左侧~20点.这样,他们确保他们不会弄乱您的应用程序的功能.想象一下,你有一个UIScrollView屏幕,你不能向右滑动,因为它不断弹出VC.这不会很好.
Apple 在这里说:
interactivePopGestureRecognizer
手势识别器负责将顶视图控制器弹出导航堆栈.(只读)
@property(非原子,只读)UIGestureRecognizer*interactivePopGestureRecognizer
导航控制器在其视图上安装此手势识别器,并使用它将最顶层的视图控制器弹出导航堆栈.您可以使用此属性检索手势识别器,并将其与用户界面中其他手势识别器的行为联系起来.将手势识别器绑在一起时,请确保他们同时识别手势,以确保您的手势识别器有机会处理事件.
所以你必须实现自己的UIGestureRecognizer,并将其行为与interactivePopGestureRecognizer你的行为联系起来UIViewController.
编辑:
这是我建立的解决方案.您可以实现符合UIViewControllerAnimatedTransitioning委托的自己的转换.此解决方案有效,但尚未经过全面测试.
您将获得一个交互式滑动过渡以弹出ViewControllers.您可以从视图中的任何位置向右滑动.
已知问题:如果启动平移并在视图宽度的一半之前停止,则转换将被取消(预期行为).在此过程中,视图将重置为其原始帧.在这个动画中,它们是一个视觉故障.
示例的类如下:
UINavigationController> ViewController> SecondViewController
CustomPopTransition.h:
#import <Foundation/Foundation.h>
@interface CustomPopTransition : NSObject <UIViewControllerAnimatedTransitioning>
@end
Run Code Online (Sandbox Code Playgroud)
CustomPopTransition.m:
#import "CustomPopTransition.h"
#import "SecondViewController.h"
#import "ViewController.h"
@implementation CustomPopTransition
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
return 0.3;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
SecondViewController *fromViewController = (SecondViewController*)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
ViewController *toViewController = (ViewController*)[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView = [transitionContext containerView];
[containerView addSubview:toViewController.view];
[containerView bringSubviewToFront:fromViewController.view];
// Setup the initial view states
toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];
[UIView animateWithDuration:0.3 animations:^{
fromViewController.view.frame = CGRectMake(toViewController.view.frame.size.width, fromViewController.view.frame.origin.y, fromViewController.view.frame.size.width, fromViewController.view.frame.size.height);
} completion:^(BOOL finished) {
// Declare that we've finished
[transitionContext completeTransition:!transitionContext.transitionWasCancelled];
}];
}
@end
Run Code Online (Sandbox Code Playgroud)
SecondViewController.h:
#import <UIKit/UIKit.h>
@interface SecondViewController : UIViewController <UINavigationControllerDelegate>
@end
Run Code Online (Sandbox Code Playgroud)
SecondViewController.m:
#import "SecondViewController.h"
#import "ViewController.h"
#import "CustomPopTransition.h"
@interface SecondViewController ()
@property (nonatomic, strong) UIPercentDrivenInteractiveTransition *interactivePopTransition;
@end
@implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.delegate = self;
UIPanGestureRecognizer *popRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePopRecognizer:)];
[self.view addGestureRecognizer:popRecognizer];
}
-(void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
// Stop being the navigation controller's delegate
if (self.navigationController.delegate == self) {
self.navigationController.delegate = nil;
}
}
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
// Check if we're transitioning from this view controller to a DSLSecondViewController
if (fromVC == self && [toVC isKindOfClass:[ViewController class]]) {
return [[CustomPopTransition alloc] init];
}
else {
return nil;
}
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
// Check if this is for our custom transition
if ([animationController isKindOfClass:[CustomPopTransition class]]) {
return self.interactivePopTransition;
}
else {
return nil;
}
}
- (void)handlePopRecognizer:(UIPanGestureRecognizer*)recognizer {
// Calculate how far the user has dragged across the view
CGFloat progress = [recognizer translationInView:self.view].x / (self.view.bounds.size.width * 1.0);
progress = MIN(1.0, MAX(0.0, progress));
if (recognizer.state == UIGestureRecognizerStateBegan) {
NSLog(@"began");
// Create a interactive transition and pop the view controller
self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
[self.navigationController popViewControllerAnimated:YES];
}
else if (recognizer.state == UIGestureRecognizerStateChanged) {
NSLog(@"changed");
// Update the interactive transition's progress
[self.interactivePopTransition updateInteractiveTransition:progress];
}
else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
NSLog(@"ended/cancelled");
// Finish or cancel the interactive transition
if (progress > 0.5) {
[self.interactivePopTransition finishInteractiveTransition];
}
else {
[self.interactivePopTransition cancelInteractiveTransition];
}
self.interactivePopTransition = nil;
}
}
@end
Run Code Online (Sandbox Code Playgroud)
创建平移手势识别器并移动交互式流行手势识别器的目标。
将您的识别器添加到推送的视图控制器的 viewDidLoad 中,瞧!
let popGestureRecognizer = self.navigationController!.interactivePopGestureRecognizer!
if let targets = popGestureRecognizer.value(forKey: "targets") as? NSMutableArray {
let gestureRecognizer = UIPanGestureRecognizer()
gestureRecognizer.setValue(targets, forKey: "targets")
self.view.addGestureRecognizer(gestureRecognizer)
}
Run Code Online (Sandbox Code Playgroud)
这是一个Swift版本的Spynet的答案,只有一些修改.首先,我为UIView动画定义了一条线性曲线.其次,我在下面的视图中添加了一个半透明的黑色背景,以获得更好的效果.第三,我已经分组了一个UINavigationController.这允许将转换应用于UINavigationController中的任何"Pop"转换.这是代码:
CustomPopTransition.swift
import UIKit
class CustomPopTransition: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
else {
return
}
let containerView = transitionContext.containerView
containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)
// Setup the initial view states
toViewController.view.frame = CGRect(x: -100, y: toViewController.view.frame.origin.y, width: fromViewController.view.frame.size.width, height: fromViewController.view.frame.size.height)
let dimmingView = UIView(frame: CGRect(x: 0,y: 0, width: toViewController.view.frame.width, height: toViewController.view.frame.height))
dimmingView.backgroundColor = UIColor.black
dimmingView.alpha = 0.5
toViewController.view.addSubview(dimmingView)
UIView.animate(withDuration: transitionDuration(using: transitionContext),
delay: 0,
options: UIView.AnimationOptions.curveLinear,
animations: {
dimmingView.alpha = 0
toViewController.view.frame = transitionContext.finalFrame(for: toViewController)
fromViewController.view.frame = CGRect(x: toViewController.view.frame.size.width, y: fromViewController.view.frame.origin.y, width: fromViewController.view.frame.size.width, height: fromViewController.view.frame.size.height)
},
completion: { finished in
dimmingView.removeFromSuperview()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
)
}
}
Run Code Online (Sandbox Code Playgroud)
PoppingNavigationController.swift
import UIKit
class PoppingNavigationController : UINavigationController, UINavigationControllerDelegate {
var interactivePopTransition: UIPercentDrivenInteractiveTransition!
override func viewDidLoad() {
self.delegate = self
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
addPanGesture(viewController: viewController)
}
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if (operation == .pop) {
return CustomPopTransition()
}
else {
return nil
}
}
func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
if animationController.isKind(of: CustomPopTransition.self) {
return interactivePopTransition
}
else {
return nil
}
}
func addPanGesture(viewController: UIViewController) {
let popRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanRecognizer(recognizer:)))
viewController.view.addGestureRecognizer(popRecognizer)
}
@objc
func handlePanRecognizer(recognizer: UIPanGestureRecognizer) {
// Calculate how far the user has dragged across the view
var progress = recognizer.translation(in: self.view).x / self.view.bounds.size.width
progress = min(1, max(0, progress))
if (recognizer.state == .began) {
// Create a interactive transition and pop the view controller
self.interactivePopTransition = UIPercentDrivenInteractiveTransition()
self.popViewController(animated: true)
}
else if (recognizer.state == .changed) {
// Update the interactive transition's progress
interactivePopTransition.update(progress)
}
else if (recognizer.state == .ended || recognizer.state == .cancelled) {
// Finish or cancel the interactive transition
if (progress > 0.5) {
interactivePopTransition.finish()
}
else {
interactivePopTransition.cancel()
}
interactivePopTransition = nil
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10442 次 |
| 最近记录: |