选择不同的UIPanGestureRecognizer触摸

时间:2015-11-02 22:06:01

标签: nsuserdefaults uiswitch uipangesturerecognizer

好的,我有一个带有左菜单和右视图控制器的应用程序,它们由UIPanGestureRecognizer控制。因此,当用户滑动屏幕边缘的边框(20px)时,它会导航。

在设置视图控制器中,我有UISwitch控制其他各种东西,但其中一个我想控制UIPanGestureRecognizer将接触多少次。

交换机设置正确,并将用户默认值发送到另一个视图控制器,但在接收端,它不会读取用户选择的内容。

UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureCallback:)];

//Switch for SwipeNav
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL switchOn = [userDefaults boolForKey:@"SwipeNav"];

if (switchOn) {
    // 2 Finger SwipeNav
    [pan setMinimumNumberOfTouches:2];
    [pan setMaximumNumberOfTouches:2];

}else{
    [pan setMinimumNumberOfTouches:1];
    [pan setMaximumNumberOfTouches:1];
}
[pan setDelegate:self];
[self.view addGestureRecognizer:pan];

当开关打开时,我怎么能这样做,它使用2个触摸来导航,然后关闭它就像正常一样?

任何帮助都会受到赞赏。谢谢。

使用设置同步代码更新。

    if (swipe){
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setBool:self.swipe.on forKey:@"SwipeNav"];
    [userDefaults synchronize];

    if ([swipe isOn]) {
        [swipe setOn:YES animated:YES];
        [self.tableView reloadData];
        [[UIApplication sharedApplication] reloadInputViews];

    } else {
        [swipe setOn:NO animated:YES];
        [self.tableView reloadData];
        [[UIApplication sharedApplication] reloadInputViews];
    }
}

2 个答案:

答案 0 :(得分:0)

我创建了一个新项目,并尝试重现您所看到的问题,一切似乎都按预期工作。当开关打开时,你需要两个按钮来平移,当开关关闭时你只需要一个。如果这指向正确的方向,请告诉我。你的代码似乎是正确的。

我从How to use UIPanGestureRecognizer to move object? iPhone/iPad

复制粘贴了handlePan函数

以编程方式创建所有内容并复制粘贴代码以保存交换机的状态。这是两个UIViewControllers

的代码
//
//  ViewController.m
//  StackOverflowSwitch
//
//  
// 
//

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) UIButton *myButton;
@property (nonatomic,strong) UISwitch *switchOn;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.myButton = [[UIButton alloc]initWithFrame:CGRectMake(10, 100, 150, 150)];
    self.switchOn = [[UISwitch alloc]initWithFrame:CGRectMake(10, 300, 100, 100)];
    self.myButton.backgroundColor =[UIColor grayColor];
    [self.myButton setTitle:@"Click Me" forState:UIControlStateNormal];
    [self.myButton addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.switchOn];
    [self.view addSubview:self.myButton];
    // Do any additional setup after loading the view, typically from a nib.
}

-(void)click:(UIButton *)sender
{
    [self performSegueWithIdentifier:@"NextViewController" sender:self];
}


-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    if(self.switchOn.on){
        NSLog(@"switch is on");
    }else{
        NSLog(@"switch is off");
    }
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setBool:self.switchOn.on forKey:@"SwipeNav"];
    [userDefaults synchronize];

}

@end

//////

#import "SecondViewController.h"
@interface SecondViewController() <UIGestureRecognizerDelegate>

@property (strong,nonatomic) UIView *myView;

@end


@implementation SecondViewController



-(void)viewDidLoad
{
    [super viewDidLoad];
    self.myView = [[UIView alloc]initWithFrame:CGRectMake(10, 10, 200, 200)];
    self.myView.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.myView];

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    BOOL switchOn = [userDefaults boolForKey:@"SwipeNav"];

    if (switchOn) {
        // 2 Finger SwipeNav
        [pan setMinimumNumberOfTouches:2];
        [pan setMaximumNumberOfTouches:2];

    }else{
        [pan setMinimumNumberOfTouches:1];
        [pan setMaximumNumberOfTouches:1];
    }
    [pan setDelegate:self];
    [self.view addGestureRecognizer:pan];



    [self.myView addGestureRecognizer:pan];
}


-(void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    CGPoint translation = [recognizer translationInView:self.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
                                         recognizer.view.center.y + translation.y);
    [recognizer setTranslation:CGPointMake(0, 0) inView:self.view];

    if (recognizer.state == UIGestureRecognizerStateEnded) {

        CGPoint velocity = [recognizer velocityInView:self.view];
        CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
        CGFloat slideMult = magnitude / 200;
        NSLog(@"magnitude: %f, slideMult: %f", magnitude, slideMult);

        float slideFactor = 0.1 * slideMult; // Increase for more of a slide
        CGPoint finalPoint = CGPointMake(recognizer.view.center.x + (velocity.x * slideFactor),
                                         recognizer.view.center.y + (velocity.y * slideFactor));
        finalPoint.x = MIN(MAX(finalPoint.x, 0), self.view.bounds.size.width);
        finalPoint.y = MIN(MAX(finalPoint.y, 0), self.view.bounds.size.height);

        [UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            recognizer.view.center = finalPoint;
        } completion:nil];

    }
}

@end

/////更新

我不确定[[UIApplication sharedApplication] reloadInputViews];如何调用函数来更新代码中的UIPanGestureRecongizer,但我尝试通过调用每个setupView方法尽可能接近地重新创建您的功能我点击UISwitch的时间 我在那里创建了一个带有UIPanGestureReconginzer的自定义视图,以及一个我从UIViewController调用以更新setNumberOfTouches的方法。视图按预期工作。这里的关键不是初始化新的UIPanGuestureRecongizer,而是更新现有的UIViewController。我假设您的应用UIViewUIPanGuestureRecongizerUIPanGuestureRecongizer没有完全重新加载。
我创建了一个属性#import "MyTestView.h" @interface MyTestView() <UIGestureRecognizerDelegate> @property(nonatomic,strong) UIPanGestureRecognizer *panGesture; @end @implementation MyTestView -(instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self setupView]; } return self; } -(UIPanGestureRecognizer *)panGesture { //lazy instantiation if (!_panGesture) { _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; } return _panGesture; } -(void)setupView { //this gets called everytime the UISwitch is being pressed. NSLog(@"Setup views"); self.backgroundColor = [UIColor redColor]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; BOOL switchOn = [userDefaults boolForKey:@"SwipeNav"]; if (switchOn) { // 2 Finger SwipeNav [self.panGesture setMinimumNumberOfTouches:2]; [self.panGesture setMaximumNumberOfTouches:2]; }else{ [self.panGesture setMinimumNumberOfTouches:1]; [self.panGesture setMaximumNumberOfTouches:1]; } [self.panGesture setDelegate:self]; [self addGestureRecognizer:self.panGesture]; } -(void)handlePan:(UIPanGestureRecognizer *)recognizer { CGPoint translation = [recognizer translationInView:self]; recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y); [recognizer setTranslation:CGPointMake(0, 0) inView:self]; if (recognizer.state == UIGestureRecognizerStateEnded) { CGPoint velocity = [recognizer velocityInView:self]; CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y)); CGFloat slideMult = magnitude / 200; NSLog(@"magnitude: %f, slideMult: %f", magnitude, slideMult); float slideFactor = 0.1 * slideMult; // Increase for more of a slide CGPoint finalPoint = CGPointMake(recognizer.view.center.x + (velocity.x * slideFactor), recognizer.view.center.y + (velocity.y * slideFactor)); finalPoint.x = MIN(MAX(finalPoint.x, 0), self.bounds.size.width); finalPoint.y = MIN(MAX(finalPoint.y, 0), self.bounds.size.height); [UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ recognizer.view.center = finalPoint; } completion:nil]; } } @end ,它在第一次被访问时被初始化,然后在按下开关时被更新。这是自定义UIView代码。如果您对代码有任何疑问,请与我们联系。

df = df.T

答案 1 :(得分:0)

好吧,经过多次测试/代码翻转后,我想我找到了解决方案。

所以多一点背景故事,我使用MMDrawerController,所以上面的方法关于放置[self setupView]; in(instancetype)initWithCoder没有做任何事情。 setupView或我的情况称为“setupGestureRecognizers”,它被加载到viewDidLoad中。其他任何地方根本不会加载手势。

使用我当前的切换代码和手势加载,我有:

    -(UIPanGestureRecognizer *)panGestureNav {

    if (!_panGesture) {
        _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureCallback:)];
    }

    return _panGesture;
}

-(void)setupGestureRecognizers{

    switchOn = [[NSUserDefaults standardUserDefaults] boolForKey:@"SwipeNav"];

    if (switchOn == YES) {
        // 2 Finger SwipeNav
        [self.panGestureNav setMinimumNumberOfTouches:2];
        [self.panGestureNav setMaximumNumberOfTouches:2];
        NSLog(@"2 Finger Nav");

    }else {
        [self.panGestureNav setMinimumNumberOfTouches:1];
        [self.panGestureNav setMaximumNumberOfTouches:1];
        NSLog(@"Normal Nav");
    }
    [self.panGestureNav setDelegate:self];
    [self.view addGestureRecognizer:self.panGestureNav];

    UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureCallback:)];
    [tap setDelegate:self];
    [self.view addGestureRecognizer:tap];

}

这通常会有效,但是这个库做的事情有所不同,所以我必须调查他们的手势调用以及我最终做的是在这里调用它:

-(MMOpenDrawerGestureMode)possibleOpenGestureModesForGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer withTouch:(UITouch*)touch{
    CGPoint point = [touch locationInView:self.childControllerContainerView];
    MMOpenDrawerGestureMode possibleOpenGestureModes = MMOpenDrawerGestureModeNone;
    if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]){

        [self setupGestureRecognizers]; <------------

所以现在它按照我的意愿加载和运行。

谢谢你,所以你的帮助。希望这有助于某人。