我有一个UIPickerView,在不使用时会逐渐消失为20%alpha。我希望用户能够触摸选择器并将其淡入。
如果我在主视图上放置touchesBegan方法,我可以使用它,但这仅在用户触摸View时才有效。我尝试对UIPickerView进行子类化并在那里使用touchesBegan,但它没有用。
我猜测它与Responder链有关,但似乎无法解决这个问题。
答案 0 :(得分:10)
我一直在寻找这个问题的解决方案超过一周。即使你的问题超过一年,我也会回答你的问题,希望能帮到别人。
很抱歉,如果我的语言不是非常技术性,但我对Objective-C和iPhone开发很新。
子类化UIpickerView是正确的方法。但是你要覆盖- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
方法。无论何时触摸屏幕,都会调用此方法,并返回将对触摸作出反应的视图。换句话说,将调用touchesBegan:withEvent:
方法的视图。
UIPickerView有9个子视图!在UIPickerView类中,实现- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
将不会返回self
(这意味着您在子类中编写的touchesBegan:withEvent:
将不会被调用)但会返回一个子视图,完全是索引处的视图4(一个名为UIPickerTable的未记录的子类)。
诀窍是让- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
方法返回self
,以便您可以控制touchesBegan:withEvent:
,touchesMoved:withEvent:
和touchesEnded:withEvent:
方法。
在这些方法中,为了保持UIPickerView的标准功能,你必须记得再次调用它们,但是在UIPickerTable子视图上。
我希望这是有道理的。我现在无法编写代码,只要我在家,我就会编辑这个答案并添加一些代码。
答案 1 :(得分:8)
以下是一些可以满足您需求的代码:
@interface TouchDetectionView : UIPickerView {
}
- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation TouchDetectionView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
[hitTestView touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
[hitTestView touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
[hitTestView touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
UIView * hitTestView = [self getNextResponderView:touches withEvent:event];
[hitTestView touchesCancelled:touches withEvent:event];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
return self;
}
- (UIView *)getNextResponderView:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch * touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
UIView * hitTestView = [super hitTest:point withEvent:event];
return ( hitTestView == self ) ? nil : hitTestView;
}
答案 2 :(得分:1)
上述两个答案都非常有用,但我在UIScrollView中嵌套了UIPickerView。当GUI存在时,我也在屏幕上的其他地方继续渲染。问题是UIPickerView在以下情况下不会完全更新:点击未选择的行,移动选择器以使两行跨越选择区域,或者拖动一行但手指滑动到UIPickerView之外。然后,直到UIScrollView被移动,选择器立即更新。这个结果太丑了。
问题的原因:我的持续渲染是让UIPickerView的动画无法获得完成所需的CPU周期,从而显示正确的当前选择。我的解决方案 - 工作原理 - 是这样的:在UIPickerView的touchesEnded:withEvent:
中,执行一些操作暂停我的渲染。这是代码:
#import "SubUIPickerView.h"
@implementation SubUIPickerView
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
[pickerTable touchesBegan:touches withEvent:event];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
[pickerTable touchesMoved:touches withEvent:event];
}
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
[singleton set_secondsPauseRendering:0.5f]; // <-- my code to pause rendering
[pickerTable touchesEnded:touches withEvent:event];
}
- (void) touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
[pickerTable touchesCancelled:touches withEvent:event];
}
- (UIView*) hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
if (CGRectContainsPoint(self.bounds, point))
{
if (pickerTable == nil)
{
int nSubviews = self.subviews.count;
for (int i = 0; i < nSubviews; ++i)
{
UIView* view = (UIView*) [self.subviews objectAtIndex:i];
if ([view isKindOfClass:NSClassFromString(@"UIPickerTable")])
{
pickerTable = (UIPickerTable*) view;
break;
}
}
}
return self; // i.e., *WE* will respond to the hit and pass it to UIPickerTable, above.
}
return [super hitTest:point withEvent:event];
}
@end
然后是标题,SubUIPickerView.h:
@class UIPickerTable;
@interface SubUIPickerView : UIPickerView
{
UIPickerTable* pickerTable;
}
@end
像我说的那样,这很有效。渲染暂停另外1/2秒(当您滑动UIScrollView时它已经暂停)允许UIPickerView动画完成。使用NSClassFromString()意味着您没有使用任何未记录的API。与Responder链混淆是没有必要的。感谢checcco和Tylerc230帮我提出了自己的解决方案!
答案 3 :(得分:1)
找不到最新,更简单的解决方案,因此我索要一些解决方案。创建了一个在选择器视图上延伸的不可见按钮。使用“ Touch Down”识别器将该按钮连接到我的父UIView。现在可以添加任何功能,当有人触摸选择器视图时,我碰巧需要一个随机选择计时器来使它失效。不是很优雅,但是可以。
答案 4 :(得分:0)
将父视图的canCancelContentTouches和delayedContentTouches设置为NO,这对我有用