2012-01-18 2 views
1

Я добавляю uipickerview в качестве подзапроса основного вида. Чтобы отклонить pickerview при нажатии на представление backgroud, я добавляю 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

попробовать isMemberOfClass вместо isKindOfClass ... –

+0

@Ankit не работает ... – PgmFreek

ответ

1

Я закодировал решение для вашего конкретного требования.

Во-первых, я реализовал ваш код, как вы описали, и заметили ту же проблему, о которой вы сообщали, - события ложного нажатия, которые отправляются обработчику, когда вы нажимаете на что-либо, включая UIButton.

Это объяснило мне, что UITapGestureRecogniser «украл» штрихи, которые должны были отправиться в UIButton, поэтому я решил, что самым простым и прагматичным решением было использование этой функции в моих интересах, и поэтому я назначил UITapGestureRecogniser для обоих pickerview и кнопку также. краны для pickerview, которые мы просто отбрасываем, остальные мы разбираем и передаем обработчик крана кнопки.

примечание - для удобства я назначил источник данных pickerview и делегировал его в xib. вам также нужно будет это сделать или установить в коде.

Заголовок

// 
// 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

note Примечание. В этом примере есть заглушки по умолчанию, которые XCode 4.2 создает автоматически, соответствующий код до и включает viewDidLoad. (элемент делегата в сборнике находится в конце, внутри #pragma marks) – unsynchronized

+0

также обратите внимание - я понимаю, что вы уже можете «отклонить» pickerview, и проблема, с которой вы столкнулись, связана с ложными срабатываниями. этот пример не отменяет выбор, но просто вызывает NSLog. чтобы отклонить выбор, вы можете либо использовать picker1.hidden = YES; или удалить [picker1 removeFromSuperview]; (в этом случае вам придется иметь дело с добавлением его обратно позже) – unsynchronized

1

Возможно, что вид, затронутый (touch.view), является одним из подзаголовков pickerview. Я бы попробовал:

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

Когда я нажав внутри ячейки pickerview, проблема все еще существует – PgmFreek

+0

Итак? Вы использовали вышеуказанный код? –

+0

yes..but, когда я постучал внутрь pickerview, кроме ячейки, он работает нормально. – PgmFreek

0

Я просто добавил невидимый UIControl экземпляр позади UIPickerView, которая охватывает все окно, и получает все штрихи позади 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

я реализовал следующие в Swift:

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

 Смежные вопросы

  • Нет связанных вопросов^_^