How to get stepper and longpress to coexist?

妖精的绣舞 提交于 2019-12-12 04:18:03

问题


I tried setting up a view with a longpress gesture and a stepper configured for continuous updates. With the longpress, the continuous feature of the stepper does not occur. For now, I've disabled the longpress. I guess I don't need it. But for future reference, how would I allow for both to coexist?

Just to be clear, here is the way the screen was set up when I tried this.

  • App was set up with a simple view controller.
  • A subview was added to this view (could have been a controller, but I just made it a UIView).
  • Several labels and stepper were added to this subview.
  • The steppers were wired up as outlets and actions.
  • A longpress recognizer was added to the main view in IB.
  • For completeness, a tap gesture was also added to the main view in IB.

Taps on the main view function as expected. Taps on the steppers function as expected. Longpress on the main view functions as expected. Longpress on the stepper does not.

I modified the code called by the longpress to check for the frame of the subview and not act if the touch location was within that rectangle, but that didn't make a difference. I did not try getting the longpress to fail in that situation, but I suppose I'll try that next. EDIT: OK, maybe not. There doesn't seem to be an API for that. However, there is this kludge, that I'm not going to try.

Attached is a screen shot from profiler with an inverted call tree so you can see what each item is being called by.

darkStepped: is the IBAction that is called by the stepper. If the stepper were triggered by a gesture recognizer, wouldn't I expect to see the gesture recognizer in the call tree?


回答1:


If the stepper were triggered by a gesture recognizer, wouldn't I expect to see the gesture recognizer in the call tree?

The stack trace reveals that the stepper's _updateCount method is dispatched through a timer.

This could be related to the fact that a stepper has an "autoIncrement" mode where, as long as your keep it pressed, it will update at a given (varying) rate. So, instead of simply calling _updateCount, the stepper sets up a timer to handle this behaviour.

For whatever reason the timer is used, the timer explains why you do not see the gesture recogniser in the stack trace.

In your case what happens is that the stepper gets the touches, handles them, and do not forward them to any gesture recognisers attached to it.

This can be explained as follows, although this snippet does not explicitly mention a long press recogniser in relation to a UIStepper control:

According to Apple Docs:

Interacting with Other User Interface Controls In iOS 6.0 and later, default control actions prevent overlapping gesture recognizer behavior. For example, the default action for a button is a single tap. If you have a single tap gesture recognizer attached to a button’s parent view, and the user taps the button, then the button’s action method receives the touch event instead of the gesture recognizer. This applies only to gesture recognition that overlaps the default action for a control, which includes:

A single finger single tap on a UIButton, UISwitch, UIStepper, UISegmentedControl, and UIPageControl.

...

If you have a custom subclass of one of these controls and you want to change the default action, attach a gesture recognizer directly to the control instead of to the parent view. Then, the gesture recognizer receives the touch event first. As always, be sure to read the iOS Human Interface Guidelines to ensure that your app offers an intuitive user experience, especially when overriding the default behavior of a standard control.

So, it seems you can attach the gesture recogniser directly to the control (possibly you need to subclass UIStepper for this to work, I am not really sure how to interpret the last paragraph). Hopefully this will not disable the basic workings of the stepper (but maybe it will).




回答2:


After carefully reviewing Apple's docs again, I've found the solution. I added the view controller as the delegate to the longpress gesture recognizer

self.longPress.delegate = self;

(and, of course, adding <UIGestureRecognizerDelegate> to the interface, and then added this method to the view controller:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
   // Determine if the touch is inside the custom subview
   if (gestureRecognizer == self.longPress) {
      CGPoint touchLocation = [touch locationInView:self.view];
      if (CGRectContainsPoint(self.antControl.frame, touchLocation)) {
         return NO;
      }
   }
   return YES;
}

This way the gesture recognizer doesn't even get called when the longpress occurs within the frame of self.antControl, which is the subview mentioned in the question.



来源:https://stackoverflow.com/questions/20847475/how-to-get-stepper-and-longpress-to-coexist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!