2012-01-18 18 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 
      } 
     }