UIScrollView里面的UIDatePicker有页面 [英] UIDatePicker inside UIScrollView with pages

查看:119
本文介绍了UIScrollView里面的UIDatePicker有页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个2页的UIScrollView,我可以在它们之间水平滚动。但是,在我的一个页面上,我有一个UIDatePicker,滚动视图正在拦截垂直触摸事件,因此我无法再操纵日期选择器(除非点击或点击)。有没有办法告诉ScrollView将垂直触摸事件发送到日期选择器,但是将水平触摸事件发送到滚动视图以切换页面?

解决方案

我认为这个问题有两部分。第一个是确定用户的意图,第二个是获得正确的控制以响应该意图。



确定意图



我认为明确用户的意图非常重要。想象一下这种情况:用户开始触摸屏幕并将手指向左移动,但也向上移动了一点。用户可能打算滚动视图,并且根本不打算更改日期。滚动视图并更改日期会很糟糕,尤其是当它移出屏幕时。因此,为了确定用户的意图,我建议使用以下算法:



当用户开始触摸屏幕时,记录起始位置。当用户的手指开始远离该位置时,控件根本不应该做出反应。一旦触摸移动超过起始位置的某个阈值距离,确定它是否水平或垂直移动。
如果它垂直移动,则用户打算更改日期,因此忽略移动的水平部分并仅更改日期。
如果它更加水平移动,用户打算滚动视图,所以忽略移动的垂直部分,只滚动视图。



实施



为了实现这一点,您需要在UIScrollView或日期选择器之前处理事件。可能有几种方法可以做到这一点,但有一个特别想到:创建一个名为ScrollingDateMediatorView的自定义UIView。将UIScrollView设置为此视图的子级。覆盖ScrollingDateMediatorView的hitTest:withEvent:和pointInside:withEvent:方法。这些方法需要执行通常会发生的相同类型的命中测试,但如果结果是日期选择器,则返回self。这有效地劫持了发往日期选择器的任何触摸事件,允许ScrollingDateMediatorView首先处理它们。然后在各种touches *方法中实现上述算法。具体来说:



在touchesBegan:withEvent方法中,保存起始位置。



在touchesMoved中:withEvent,if尚未知道用户的意图,确定被触摸的是否已经远离起始位置移动得足够远。如果有,则确定用户是否打算滚动或更改日期,并保存该意图。
如果用户的意图已知并且要更改日期,则向日期选择器发送touchMoved:withEvent消息,否则向UIScrollView发送touchesMoved:withEvent消息。
你必须在touchesEnded中执行一些simliar工作:withEvent和touchesCancelled:withEvent以确保其他视图获得适当的消息。这两种方法都应该重置保存的值。



一旦你正确地传播事件,你可能不得不尝试一些用户测试来调整移动阈值。 / p>

I have a UIScrollView with 2 pages, and I can scroll horizontally between them. However, on one of my pages, I have a UIDatePicker, and the scroll view is intercepting the vertical touch events so I can no longer manipulate the date picker (except by clicking or tapping). Is there some way to tell the ScrollView to send the vertical touch events to the date picker, but send the horizontal touch events to the scroll view to switch pages?

解决方案

I think there's two parts to this problem. The first is determining the user's intent, and the second is getting the correct control to respond to that intent.

Determining Intent

I think it's important to be clear about what the user intends. Imagine this scenario: The user starts touching the screen and moves his finger far to the left, but also up a little. The user probably intended to scroll the view, and didn't intend to change the date at all. It would be bad to both scroll the view and change the date, especially just as it moves off-screen. So to determine what the user intends I suggest the following algorithm:

When the user starts touching the screen, record the starting position. As the user's finger starts to move away from that position, the controls should not react at all. Once the touch moves past a certain threshold distance from the starting position, determine whether it moved more horizontally or vertically. If it moved vertically, the user intends to change the date, so ignore the horizontal portion of the movement and only change the date. If it moved more horizontally, the user intends to scroll the view, so ignore the vertical portion of the movement and only scroll the view.

Implementation

In order to implement this, you need to handle the events before the UIScrollView or date picker do. There's probably a few ways to do this, but one in particular comes to mind: Make a custom UIView called ScrollingDateMediatorView. Set the UIScrollView as a child of this view. Override the ScrollingDateMediatorView's hitTest:withEvent: and pointInside:withEvent: methods. These methods need to perform the same kind of hit testing that would normally occur, but if the result is the date picker, return self instead. This effectively hijacks any touch events that were destined for the date picker, allowing the ScrollingDateMediatorView to handle them first. Then you implement the algorithm described above in the various touches* methods. Specifically:

In the touchesBegan:withEvent method, save the starting position.

In touchesMoved:withEvent, if the user's intent isn't known yet, determine whether the touched has moved far enough away from the starting position. If it has, determine whether the user intends to scroll or change the date, and save that intent. If the user's intent is already known and it's to change the date, send the date picker the touchedMoved:withEvent message, otherwise send the UIScrollView the touchesMoved:withEvent message. You'll have to do some simliar work within touchesEnded:withEvent and touchesCancelled:withEvent to make sure the other views get the appropriate messages. Both of these methods should reset the saved values.

Once you have it properly propagating events, you'll probably have to try some user testing to tune the movement threshold.

这篇关于UIScrollView里面的UIDatePicker有页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆