在点击背景时关闭UIPickerView [英] Dismissing UIPickerView on tapping background
问题描述
我要添加一个uipickerview作为主视图的子视图.为了在点击背景视图时关闭pickerview,我在主视图中添加了一个UITapGestureRecognizer.
我正在使用以下代码为主视图添加GestureRecognizer
UITapGestureRecognizer * gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap :)];gestureRecognizer.numberOfTapsRequired = 1;gestureRecognizer.numberOfTouchesRequired = 1;poseRecognizer.delegate =自我;[self.view addGestureRecognizer:gestureRecognizer];[gestureRecognizer发布];
在handleSingleTap方法中,我关闭了pickerview.
但是问题是,当我在pickerview内部点击时,还会调用handleSingleTap.为了避免这种情况,我使用了UIGestureRecognizer的以下委托方法
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer应该ReceiveTouch:(UITouch *)touch {/**如果点击位于按钮内,则返回NO,以确保检测到按钮点击.*/如果([touch.view isKindOfClass:[UIButton类]]){返回FALSE;}否则if([touch.view isKindOfClass:[UIPickerView类]]){返回FALSE;}返回TRUE;}
它适用于按钮,但不适用于 UIPickerView
.有人可以帮我吗?
我已经为您的特定要求编写了解决方案.
首先,我按照您描述的方式实现了代码,并观察到与您报告的问题相同的问题-当您轻按任何内容(包括UIButton)时,会将虚假的轻击事件发送到轻击处理程序.
这告诉我UITapGestureRecogniser正在窃取" UIButton应有的接触,因此我决定最简单,最实用的解决方案是利用该功能,以达到我的优势,因此我将UITapGestureRecogniser分配给了两者.pickerview和按钮也.我们只舍弃了pickerview的水龙头,我们解析了其他水龙头,并将其传递给按钮的水龙头处理程序.
注意-为了方便起见,我在xib中分配了pickerview的数据源和委托.您还需要这样做,或者在代码中进行设置.
标题
////ViewController.h//stackExchangeDemo////由在18/01/12上未同步创建.//通过http://stackoverflow.com/a/8908028/830899发布到公共领域//#import< UIKit/UIKit.h>@interface ViewController:UIViewController< UIPickerViewDelegate,UIPickerViewDataSource>{UIButton * btn1;UIPickerView * picker1;}@属性(保留,非原子)IBOutlet UIButton * btn1;@属性(保留,非原子)IBOutlet UIPickerView * picker1;@结尾
实施
////ViewController.m//stackExchangeDemo////由在18/01/12上未同步创建.//通过http://stackoverflow.com/a/8908028/830899发布到公共领域//#import"ViewController.h"@implementation ViewController@synthesize btn1;@synthesize picker1;-(void)didReceiveMemoryWarning{[super didReceiveMemoryWarning];//释放所有未使用的缓存数据,图像等.}#pragma mark-查看生命周期-(void)handleSingleTap:(UITapGestureRecognizer *)tapper {如果(tapper.state == UIGestureRecognizerStateEnded){NSLog(@%@",NSStringFromSelector(_cmd));}}-(IBAction)handleButtonTap:(id)sender {NSLog(@%@",NSStringFromSelector(_cmd));}-(void)handleButtonTapGesture:(UITapGestureRecognizer *)tapper {//调用按钮事件处理程序UIControlEvents eventsToHandle = UIControlEventTouchUpInside;如果(tapper.state == UIGestureRecognizerStateEnded){UIButton * btn =(UIButton *)tapper.view;for([btn actionsForTarget:self forControlEvent:eventsToHandle]中的NSString * selName){SEL动作= NSSelectorFromString(selName);如果(操作){[self performSelector:action withObject:btn1];休息;}};}}-(void)handleDummyTap:(UITapGestureRecognizer *)tapper {//静默忽略此视图的tap事件.}-(void)setupTap:(UIView *)查看动作:(SEL)动作{//为给定视图分配自定义点击事件处理程序.UITapGestureRecognizer * gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:action];[查看addGestureRecognizer:gestureRecognizer];[gestureRecognizer发布];}-(void)viewDidLoad{[super viewDidLoad];//加载视图后进行其他任何设置,通常是从笔尖进行.[self setupTap:self.view操作:@selector(handleSingleTap :)];[self setupTap:picker1操作:@selector(handleDummyTap :)];[self setupTap:btn1操作:@selector(handleButtonTapGesture :)];}-(void)viewDidUnload{[self setBtn1:nil];[self setPicker1:nil];[super viewDidUnload];//释放主视图的所有保留子视图.//例如self.myOutlet = nil;}-(void)viewWillAppear:(BOOL)动画{[super viewWillAppear:animated];}-(void)viewDidAppear:(BOOL)动画{[super viewDidAppear:animated];}-(void)viewWillDisappear:(BOOL)动画{[super viewWillDisappear:animated];}-(void)viewDidDisappear:(BOOL)动画{[super viewDidDisappear:animated];}-(BOOL)应该AutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{//对于支持的方向返回YES返回(interfaceOrientation!= UIInterfaceOrientationPortraitUpsideDown);}#pragma mark @protocol UIPickerViewDataSource< NSObject>//返回要显示的列"数.-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {返回1;}//返回每个组件中的行数.-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {返回1;}#pragma mark @protocol UIPickerViewDelegate< NSObject>-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {返回[@这么久,感谢所有的鱼".复制autorelease];}-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {NSLog(@%@",NSStringFromSelector(_cmd));}-(void)dealloc {[btn1发布];[picker1版本];[super dealloc];}@结尾
I am adding a uipickerview as the subview of the main view. To dismiss the pickerview on tapping the backgroud view, i am adding a UITapGestureRecognizer to the main view.
I am using the following code to add the GestureRecognizer for main view
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
gestureRecognizer.numberOfTapsRequired=1;
gestureRecognizer.numberOfTouchesRequired=1;
gestureRecognizer.delegate = self;
[self.view addGestureRecognizer:gestureRecognizer];
[gestureRecognizer release];
In the handleSingleTap method i am dismissing the pickerview.
But the problem is handleSingleTap is also called when I tap inside the pickerview. To avoid it i used the following delegate method of 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;
}
It is working for button,But is not working for UIPickerView
. Can anyone help me with this?
I have coded up a solution to your particular requirement.
first, i implemented your code as you have described and observed the same problem you reported - spurious tap events being sent to tap handler, when you tapped on anything, including a UIButton.
this told me that the UITapGestureRecogniser was "stealing" the touches that should have gone to the UIButton, so i decided the simplest, most pragmatic solution was to use that feature to my advantage, and so i assigned a UITapGestureRecogniser to both the pickerview and the button also. the taps for the pickerview we just discard, the others we parse and pass on to the button's tap handler.
note - for expedience i assigned the pickerview's datasource and delegate in the xib. you will need to do that also, or set it in code.
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
implementation
//
// 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
这篇关于在点击背景时关闭UIPickerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!