2012-01-18 68 views
1

我正在添加一个uipickerview作为主视图的子视图。要关闭点击背景视图的pickerview,我将添加一个UITapGestureRecognizer到主视图。关于点击背景的解除UIPickerView

我使用以下代码来添加GestureRecognizer主视图

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; 
    gestureRecognizer.numberOfTapsRequired=1; 
    gestureRecognizer.numberOfTouchesRequired=1; 
    gestureRecognizer.delegate = self; 
    [self.view addGestureRecognizer:gestureRecognizer]; 
    [gestureRecognizer release]; 

在handleSingleTap方法,我驳回pickerview。

但问题是handleSingleTap也被称为当我点击pickerview内部。为了避免它,我用UIGestureRecognizer

以下委托方法
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { 

    /* 
    *If the tap is inside a button return NO, to ensure the button click is detected. 
    */ 
    if ([touch.view isKindOfClass:[UIButton class]]){ 
     return FALSE; 
    }else if([touch.view isKindOfClass:[UIPickerView class]]) { 

     return FALSE; 

    } 
    return TRUE; 
} 

它正在为按钮,但没有工作UIPickerView。谁能帮我这个?

+0

尝试,而不是isKindOfClass isMemberOfClass ... – 2012-01-18 07:55:12

+0

@Ankit不工作... – PgmFreek 2012-01-18 08:25:37

回答

1

我已经编写了一个解决方案,您的特定要求。

第一,我实现你的代码,你所描述和观察你报了同样的问题 - 发送虚假点击事件挖掘处理,当你轻敲任何东西,包括一个UIButton。这个告诉我UITapGestureRecogniser是“窃取”应该已经到UIButton的触摸,所以我决定最简单,最实用的解决方案是使用该功能对我有利,所以我为它分配了一个UITapGestureRecogniser pickerview和按钮也。我们刚刚丢弃的pickerview的水龙头,我们解析并传递给按钮的水龙头处理器的水龙头。

注 - 为了方便起见,我在xib中分配了pickerview的数据源和委托。您还需要这样做,或者将其设置为代码。

// 
// ViewController.h 
// stackExchangeDemo 
// 
// Created by unsynchronized on 18/01/12. 
// released to public domain via http://stackoverflow.com/a/8908028/830899 
// 

#import <UIKit/UIKit.h> 

@interface ViewController : UIViewController 
<UIPickerViewDelegate, UIPickerViewDataSource> 

{ 
    UIButton *btn1; 
    UIPickerView *picker1; 
} 

@property (retain, nonatomic) IBOutlet UIButton *btn1; 
@property (retain, nonatomic) IBOutlet UIPickerView *picker1; 

@end 

实施

// 
// ViewController.m 
// stackExchangeDemo 
// 
// Created by unsynchronized on 18/01/12. 
// released to public domain via http://stackoverflow.com/a/8908028/830899 
// 

#import "ViewController.h" 

@implementation ViewController 
@synthesize btn1; 
@synthesize picker1; 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Release any cached data, images, etc that aren't in use. 
} 

#pragma mark - View lifecycle 

-(void) handleSingleTap:(UITapGestureRecognizer *) tapper { 

    if (tapper.state == UIGestureRecognizerStateEnded) { 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 
    } 

} 

- (IBAction)handleButtonTap:(id)sender { 
    NSLog(@"%@",NSStringFromSelector(_cmd)); 
} 


-(void) handleButtonTapGesture:(UITapGestureRecognizer *) tapper { 
    // call the buttons event handler 

    UIControlEvents eventsToHandle = UIControlEventTouchUpInside; 

    if (tapper.state == UIGestureRecognizerStateEnded) { 
     UIButton *btn = (UIButton *) tapper.view; 

     for (NSString *selName in [btn actionsForTarget:self forControlEvent:eventsToHandle]) { 

      SEL action = NSSelectorFromString(selName); 
      if (action) { 

       [self performSelector:action withObject:btn1]; 
       break; 
      } 

     }; 


    } 

} 

-(void) handleDummyTap:(UITapGestureRecognizer *) tapper { 
    // silently ignore the tap event for this view. 
} 

-(void) setupTap:(UIView *) view action:(SEL)action { 
    // assign custom tap event handler for given view. 
    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:action]; 
    [view addGestureRecognizer:gestureRecognizer]; 
    [gestureRecognizer release];  
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    [self setupTap:self.view action:@selector(handleSingleTap:)]; 
    [self setupTap:picker1 action:@selector(handleDummyTap:)]; 
    [self setupTap:btn1 action:@selector(handleButtonTapGesture:)]; 



} 



- (void)viewDidUnload 
{ 
    [self setBtn1:nil]; 
    [self setPicker1:nil]; 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
} 

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 
} 


#pragma mark @protocol UIPickerViewDataSource<NSObject> 

// returns the number of 'columns' to display. 
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ 
    return 1; 
} 

// returns the # of rows in each component.. 
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 

    return 1; 
} 


#pragma mark @protocol UIPickerViewDelegate<NSObject> 
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 
    return [@"so long and thanks for all the fish".copy autorelease ]; 
} 


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{ 
    NSLog(@"%@",NSStringFromSelector(_cmd)); 

} 

- (void)dealloc { 
    [btn1 release]; 
    [picker1 release]; 
    [super dealloc]; 
} 
@end 
+0

注意 - 此示例具有XCode 4.2自动创建的默认存根,相关代码可达到并包括viewDidLoad。 (picker view委托的东西在最后,在#pragma标记里面) – unsynchronized 2012-01-18 09:57:35

+0

也注意到 - 我认为你已经能够“解雇”pickerview,并且你遇到的问题是错误的触发器。这个例子并不关闭pickerview,只是简单地调用NSLog。要关闭pickerview,你可以使用picker1.hidden = YES;或者移除[picker1 removeFromSuperview]; (在这种情况下,您需要处理稍后再添加它) – unsynchronized 2012-01-18 10:03:49

1

触摸的视图(touch.view)可能是pickerview的子视图之一。我会尝试测试:

[[pickerview subviews] containsObject: touch.view]; 
+0

当我挖掘pickerview单元格内,问题仍然存在 – PgmFreek 2012-01-18 07:40:44

+0

因此?你使用了上面的代码吗? – 2012-01-18 07:41:36

+0

是的..但是当我点击pickerview而不是单元格时它工作正常。 – PgmFreek 2012-01-18 07:42:43

0

我只是增加了UIPickerView,覆盖所有的窗户后面一种无形的UIControl实例,并得到一切的背后UIPickerView的接触。如果它被触摸,那么UIPickerView和UIControl都将被解雇。 (SelectButton和CancelButton是辅助按钮UIPickerView)

@property (strong, nonatomic) UIControl *touchRecognizer; 

- (IBAction)showPicker:(id)sender { 

    self.touchRecognizer = [[UIControl alloc]initWithFrame:self.view.window.bounds]; 
    [self.view.window addSubview:self.touchRecognizer]; 
    [self.touchRecognizer addTarget:self action:@selector(touchedOutsidePicker:) forControlEvents:UIControlEventTouchUpInside]; 

    [self.textField becomeFirstResponder]; 
} 

- (IBAction)touchedOutsidePicker:(id)sender { 
    [self.touchRecognizer removeFromSuperview]; 
    self.touchRecognizer = nil; 

    [self.textField resignFirstResponder]; 
} 

-(void)selectButtonPressed:(id)sender{ 
    [self.touchRecognizer removeFromSuperview]; 
    self.touchRecognizer = nil; 

    [self.textField resignFirstResponder]; 

} 

-(void)cancelButtonPressed:(id)sender{ 
    [self.touchRecognizer removeFromSuperview]; 
    self.touchRecognizer = nil; 

    [self.textField resignFirstResponder]; 
} 
0

我实现了在斯威夫特以下几点:

override func viewDidLoad() 
     { 
      super.viewDidLoad() 
      let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture)) 
      tap.cancelsTouchesInView = false 
      view.addGestureRecognizer(tap) 
     } 

     func handleTapGesture(sender: AnyObject) 
     { 
      let subview = view?.hitTest(sender.locationInView(view), withEvent: nil) 

      if(!(subview?.isDescendantOfView(timePicker) ?? false)) 
      {//might want to add a condition to make sure it's not your button ^^ 
       showTimePicker(false)//method which handles showing/hiding my picker 
      } 
     }