Jas*_*ens 4 iphone objective-c uidatepicker scrollview
我有一个2页的UIScrollView,我可以在它们之间水平滚动.但是,在我的一个页面上,我有一个UIDatePicker,滚动视图正在拦截垂直触摸事件,因此我无法再操纵日期选择器(通过单击或点击除外).有没有办法告诉ScrollView将垂直触摸事件发送到日期选择器,但是将水平触摸事件发送到滚动视图以切换页面?
实际上,实施起来比Bob建议的要简单得多.这对我来说非常适合.如果您还没有UIScrollview,则需要将其子类化,并包含此方法: -
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if ([result.superview isKindOfClass:[UIPickerView class]])
{
self.canCancelContentTouches = NO;
self.delaysContentTouches = NO;
}
else
{
self.canCancelContentTouches = YES; // (or restore bool from prev value if needed)
self.delaysContentTouches = YES; // (same as above)
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
我使用的原因result.superview是获取触摸的视图实际上是UIPickerTable,它是一个私有API.
干杯
我认为这个问题有两部分.第一个是确定用户的意图,第二个是获得正确的控制以响应该意图.
我认为明确用户的意图非常重要.想象一下这种情况:用户开始触摸屏幕并将手指向左移动,但也向上移动一点.用户可能打算滚动视图,并且根本不打算更改日期.滚动视图并更改日期会很糟糕,尤其是当它移出屏幕时.因此,为了确定用户的意图,我建议使用以下算法:
当用户开始触摸屏幕时,记录起始位置.当用户的手指开始远离该位置时,控件根本不应该做出反应.一旦触摸移动超过起始位置的某个阈值距离,确定它是否水平或垂直移动.如果它垂直移动,则用户打算更改日期,因此忽略移动的水平部分并仅更改日期.如果它更加水平移动,则用户打算滚动视图,因此忽略移动的垂直部分并仅滚动视图.
为了实现这一点,您需要在UIScrollView或日期选择器之前处理事件.可能有几种方法可以做到这一点,但有一个特别想到:创建一个名为ScrollingDateMediatorView的自定义UIView.将UIScrollView设置为此视图的子级.覆盖ScrollingDateMediatorView的hitTest:withEvent:和pointInside:withEvent:方法.这些方法需要执行通常会发生的相同类型的命中测试,但如果结果是日期选择器,则返回self.这有效地劫持了发往日期选择器的任何触摸事件,允许ScrollingDateMediatorView首先处理它们.然后在各种touches*方法中实现上述算法.特别:
在touchesBegan:withEvent方法中,保存起始位置.
在touchesMoved:withEvent中,如果尚未知道用户的意图,请确定被触摸的移动距离起始位置是否足够远.如果有,则确定用户是否打算滚动或更改日期,并保存该意图.如果用户的意图已知并且要更改日期,则向日期选择器发送touchMoved:withEvent消息,否则向UIScrollView发送touchesMoved:withEvent消息.你必须在touchesEnded中做一些简单的工作:withEvent和touchesCancelled:withEvent以确保其他视图获得适当的消息.这两种方法都应该重置保存的值.
一旦你正确传播事件,你可能不得不尝试一些用户测试来调整移动阈值.