UIPicker检测当前所选行的点击

时间:2010-08-18 23:04:36

标签: iphone select touch uipickerview tap

我有一个UIPickerView,点击选定的行时,系统不会调用 didSelectRow 方法。我需要处理这个案子。有什么想法吗?

7 个答案:

答案 0 :(得分:22)

首先,使类符合UIGestureRecognizerDelegate协议

然后,在视图设置中:

UITapGestureRecognizer *tapToSelect = [[UITapGestureRecognizer alloc]initWithTarget:self
                                                                                 action:@selector(tappedToSelectRow:)];
tapToSelect.delegate = self;
[self.pickerView addGestureRecognizer:tapToSelect];

其他地方:

#pragma mark - Actions

- (IBAction)tappedToSelectRow:(UITapGestureRecognizer *)tapRecognizer
{
    if (tapRecognizer.state == UIGestureRecognizerStateEnded) {
        CGFloat rowHeight = [self.pickerView rowSizeForComponent:0].height;
        CGRect selectedRowFrame = CGRectInset(self.pickerView.bounds, 0.0, (CGRectGetHeight(self.pickerView.frame) - rowHeight) / 2.0 );
        BOOL userTappedOnSelectedRow = (CGRectContainsPoint(selectedRowFrame, [tapRecognizer locationInView:self.pickerView]));
        if (userTappedOnSelectedRow) {
            NSInteger selectedRow = [self.pickerView selectedRowInComponent:0];
            [self pickerView:self.pickerView didSelectRow:selectedRow inComponent:0];
        }
    }
}

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return true;
}

答案 1 :(得分:10)

Nikolay用 Swift 答案:

let tap = UITapGestureRecognizer(target: self, action: #selector(OCAccountSettingsViewController.pickerTapped(_:)))
tap.cancelsTouchesInView = false
tap.delegate = self
pickerView.addGestureRecognizer(tap)

重要让viewController确认 UIGestureRecognizerDelegate ,否则处理程序不会触发:

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true}

最后一步将是tap事件的处理程序:

func pickerTapped(tapRecognizer:UITapGestureRecognizer)
{
    if (tapRecognizer.state == UIGestureRecognizerState.Ended)
    {
      let rowHeight : CGFloat  = self.pickerView.rowSizeForComponent(0).height
      let selectedRowFrame: CGRect = CGRectInset(self.pickerView.bounds, 0.0, (CGRectGetHeight(self.pickerView.frame) - rowHeight) / 2.0 )
      let userTappedOnSelectedRow = (CGRectContainsPoint(selectedRowFrame, tapRecognizer.locationInView(pickerView)))
      if (userTappedOnSelectedRow)
      {
        let selectedRow = self.pickerView.selectedRowInComponent(0)
        //do whatever you want here
      }
    }
  }

答案 2 :(得分:9)

Nikolay在 Swift 4 中的回答:

首先,在UITapGestureRecognizer的{​​{1}}添加UIPickerView,让viewDidLoad()符合UIViewController

UIGestureRecognizerDelegate

添加此功能,在检测到某行时调用您的UIPickerViewDelegate:

let tap = UITapGestureRecognizer(target: self, action: #selector(pickerTapped))
tap.delegate = self
self.pickerView.addGestureRecognizer(tap)

@objc func pickerTapped(tapRecognizer: UITapGestureRecognizer) { if tapRecognizer.state == .ended { let rowHeight = self.pickerView.rowSize(forComponent: 0).height let selectedRowFrame = self.pickerView.bounds.insetBy(dx: 0, dy: (self.pickerView.frame.height - rowHeight) / 2) let userTappedOnSelectedRow = selectedRowFrame.contains(tapRecognizer.location(in: self.pickerView)) if userTappedOnSelectedRow { let selectedRow = self.pickerView.selectedRow(inComponent: 0) pickerView(self.pickerView, didSelectRow: selectedRow, inComponent: 0) } } } 添加shouldRecognizeSimultaneouslyWith方法:

UIGestureRecognizerDelegate

答案 3 :(得分:1)

这里有一个快速代码,用于确定用户是否在所选行内轻敲。我刚从Nikolay的回答中转换了obj-c代码。

func pickerTapped(sender: UITapGestureRecognizer){
    let rowHeight = self.rowSizeForComponent(0).height
    let selectedRowFrame = CGRectInset(self.bounds, 0.0, (CGRectGetHeight(self.frame) - rowHeight) / 2.0)
    let userTappedOnSelectedRow = CGRectContainsPoint(selectedRowFrame, sender.locationInView(self))
    if( userTappedOnSelectedRow ){
        // .. your action here ..
    }
}

答案 4 :(得分:0)

我通过继承一个普通的超级视图并在发送它们之前拦截触摸事件来解决这个问题。在界面构建器中,我还添加了一个选项区域的按钮,附加了一个触摸事件的动作,并将按钮发送到“后面”(这非常重要,因此它不会在hitTest中返回)。最相关的代码如下。对于更复杂的情况,例如多点触控,可以改进它。

    @implementation InterceptorView


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 UITouch *t=[touches anyObject];
 CGPoint p=[t locationInView:button];
 if ([button hitTest:p withEvent:event]) 
  started_in_button=YES;
 [hitView touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 [hitView touchesMoved:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 UITouch *t=[touches anyObject];
 CGPoint p=[t locationInView:button];
 if ([button hitTest:p withEvent:event] && started_in_button) {
  started_in_button=NO;
  [button sendActionsForControlEvents:UIControlEventTouchUpInside];
 }
 [hitView touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
 [hitView touchesCancelled:touches withEvent:event];
}

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
 hitView = [super hitTest:point withEvent:event];
 return self;
}

答案 5 :(得分:0)

这是Nikolay在Swift v3中的诀窍:

首先,使你的UIViewController实现协议UIGestureRecognizerDelegate,并将此方法添加到它:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

然后,在选择器上应用UITapGestureRecognizer,并在调用目标时调用以下扩展方法:

extension UIPickerView {
    func pickerTapped(nizer: UITapGestureRecognizer, onPick: @escaping (Int) -> ()) {
        if nizer.state == .ended {
            let rowHeight = self.rowSize(forComponent: 0).height
            let selectedRowFrame = self.bounds.insetBy(dx: 0, dy: (self.frame.height - rowHeight) / 2)

            // check if begin and end tap locations both fall into the row frame:
            if selectedRowFrame.contains(nizer.location(in: self)) &&
                   selectedRowFrame.contains(nizer.location(ofTouch: 0, in: self)) {
                onPick(self.selectedRow(inComponent: 0))
            }
        }
    }
}

答案 6 :(得分:0)

  1. 已按照建议将tapGestureRecognizer添加到pickerView中

  2. 通过

    为选择器行而不是标题提供视图

    -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)组件reusingView:(UIView *)view

  3. 在手势的回调方法中执行此操作

-(void)pickerTapped:(UIGestureRecognizer *)gestureRecognizer {

UIPickerView * pv = (id)gestureRecognizer.view;
UIView * selView = [pv viewForRow:[pv selectedRowInComponent:0]
                     forComponent:0];
CGPoint touchPoint = [gestureRecognizer locationInView:selView];
BOOL tapOnSelection = CGRectContainsPoint(selView.bounds, touchPoint);

if (tapOnSelection) ...

}

我认为比做像素数学更优雅