2012-01-18 10 views
1

メインビューのサブビューとしてuipickerviewを追加しています。バックグラウンドビューをタップしてピッカービューを閉じるには、メインビューにUITapGestureRecognizerを追加します。バックグラウンドをタップしてUIPickerViewを終了する

私は私がpickerviewを却下していますhandleSingleTap法では、メインビュー

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

ためGestureRecognizerを追加するには、次のコードを使用しています。

しかし、問題は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を試してみてください... –

+0

@Ankitが機能していない... – PgmFreek

答えて

1

私はあなたの特定の要件のソリューションをコーディングしました。

最初に、UIButtonを含む何かをタップしたときに、擬似タップイベントがタップハンドラに送信されていると報告したのと同じ問題を説明し、観察しました。

これは、UITapGestureRecogniserがUIButtonに行っていたはずのタッチを「盗んでいる」と言いました。そのため、最も簡単で実用的な解決策は、その機能を私の利点に使うことでした。したがって、私はUITapGestureRecogniserにピッカービューとボタンも表示されます。私たちが破棄した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

注 - この例には、XCode 4.2が自動的に作成するデフォルトのスタブがあり、関連するコードはviewDidLoad以下です。 (ピッカービューデリゲートのものは最後ですが、#pragma marksの中にあります) – unsynchronized

+0

メモ - 私はあなたがすでにpickerviewを "却下"することができます。この例ではpickerviewを却下しませんが、単にNSLogを呼び出します。 pickerviewを終了するには、picker1.hidden = YESを使用するか、または[picker1 removeFromSuperview]を削除します。 (この場合、後でもう一度追加する必要があります) – unsynchronized

1

タッチされたビュー(touch.view)は、ピッカービューのサブビューの1つである可能性があります。私はテストをしようとしています:

+0

とき、私ピッカービューのセル内でタップしても、問題はまだ存在する – PgmFreek

+0

だから?上記のコードを使用しましたか? –

+0

はい..しかし、セル以外のpickerviewをタップするとうまくいきます。 – PgmFreek

0

Iは、単にすべての窓を覆い、UIPickerView背後にあるすべてのタッチを取得UIPickerView、背後に不可視するuicontrolインスタンスを追加しました。タッチされた場合は、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 
      } 
     } 
関連する問題