Увольнение UIPickerView на прослушивание фона - PullRequest
1 голос
/ 18 января 2012

Я добавляю uipickerview в качестве подпредставления основного представления. Чтобы закрыть окно выбора при нажатии на фоновое изображение, я добавляю UITapGestureRecognizer в основной вид.

Я использую следующий код для добавления 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 я закрываю окно выбора.

Но проблема в том, что handleSingleTap также вызывается, когда я нажимаю в окне выбора. Чтобы избежать этого, я использовал следующий метод делегата 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. Кто-нибудь может мне помочь с этим?

Ответы [ 4 ]

1 голос
/ 18 января 2012

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

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

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

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

header

//
//  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
1 голос
/ 18 января 2012

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

[[pickerview subviews] containsObject: touch.view];
0 голосов
/ 04 августа 2016

Я реализовал в 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 
            }
         }
0 голосов
/ 26 августа 2013

Я просто добавил невидимый экземпляр 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];
}
...