首先,问题是:
当你有一个tableView如何实现时,用户可以点击NavigationBar一直滚动到顶部。
解决方案:
- (void)viewDidLoad {
UITapGestureRecognizer* tapRecon = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(navigationBarDoubleTap:)];
tapRecon.numberOfTapsRequired = 2;
[navController.navigationBar addGestureRecognizer:tapRecon];
[tapRecon release];
}
- (void)navigationBarDoubleTap:(UIGestureRecognizer*)recognizer {
[tableView setContentOffset:CGPointMake(0,0) animated:YES];
}
这就像魅力一样!
但是德拉罗克指出了一个问题:只有在没有后退按钮或rightBarButtonItem时,此方法才可行。他们的点击事件被手势识别器
覆盖我的问题:
我怎样才能拥有可导航我的NavigationBar可以点击但仍能使用我的应用程序中的后退按钮的好功能?
因此要么找到一个不会覆盖后退按钮的其他解决方案,要么找到一个解决方案让后退按钮恢复工作:)
答案 0 :(得分:15)
我没有使用位置视图,而是通过检查UITouch的类来解决这个问题。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return (![[[touch view] class] isSubclassOfClass:[UIControl class]]);
}
请注意,导航按钮的类型为UINavigationButton
,未公开,因此子类检查。
此方法位于您指定为手势识别器的委托的类中。如果您刚刚开始使用手势识别器,请注意委托是与目标分开设置的。
答案 1 :(得分:7)
UIGestureRecognizerDelegate有一个名为“gestureRecognizer:shouldReceiveTouch”的方法。如果你能够指出触摸的视图是否是按钮,只需让它返回“否”,否则返回“是”,你就可以了。
答案 2 :(得分:5)
UIGestureRecognizer
也有一个属性@property(nonatomic) BOOL cancelsTouchesInView
。来自文档:A Boolean value affecting whether touches are delivered to a view when a gesture is recognized.
所以,如果你只是做
tapRecon.cancelsTouchesInView = NO;
这可能是一个更简单的解决方案,具体取决于您的使用案例。这是我在我的应用程序中执行此操作的方式。
当按下导航栏中的按钮时,会执行其操作(根据需要),但也会执行UIGestureRecognizer
的操作。如果这不打扰你,那么这将是我能想到的最简单的解决方案。
答案 3 :(得分:2)
iOS7版本:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
CGPoint point = [touch locationInView:touch.view];
UINavigationBar *naviagationBar = (UINavigationBar *)touch.view;
NSString *navigationItemViewClass = [NSString stringWithFormat:@"UINavigationItem%@%@",@"Button",@"View"];
for (id subview in naviagationBar.subviews) {
if (([subview isKindOfClass:[UIControl class]] ||
[subview isKindOfClass:NSClassFromString(navigationItemViewClass)]) &&
[subview pointInside:point withEvent:nil]) {
return NO;
}
}
return YES;
}
编辑:后退按钮手势一角的东西仍然被覆盖,所以你这个代码而不是pointInside:withEvent
:
CGRectContainsPoint((CGRect){ .origin = subview.frame.origin, .size = CGSizeMake(subview.frame.size.width + 16, subview.frame.size.height)}, point)
答案 4 :(得分:0)
Xamarin.iOS不会在私有API中公开Objective-C类的C#包装器,因此上面@ ben-flynn建议的整齐的子类检查在这里不起作用。
一种有点狡猾的解决方法是检查视图的Description
字段:
navigationTitleTap = new UITapGestureRecognizer (tap => DidTapNavigationTitle());
navigationTitleTap.ShouldReceiveTouch = (recognizer, touch) =>
touch.View.Subviews.Any(sv =>
// Is this the NavigationBar's title or prompt?
(sv.Description.StartsWith("<UINavigationItemView") || sv.Description.StartsWith("<UINavBarPrompt")) &&
// Was the nested label actually tapped?
sv.Subviews.OfType<UILabel>().Any(label =>
label.Frame.Contains(touch.LocationInView(sv))));
NavigationController.NavigationBar.AddGestureRecognizer (navigationTitleTap);
Linq集合过滤器.OfType<T>
在视图层次结构中捕获某些类型时非常方便。
答案 5 :(得分:0)
这对我有用,它基于斯塔瓦什的回答。我使用手势识别器的view属性在委托方法中返回YES / NO。
这是一个旧的应用程序,所以显然这不是ARC,不使用新的布局内容也不使用NSAttributed字符串。我把它留给你:p
- (void)viewDidLoad
{
...
CGRect r = self.navigationController.navigationBar.bounds;
UILabel *titleView = [[UILabel alloc] initWithFrame:r];
titleView.autoresizingMask =
UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
titleView.textAlignment = NSTextAlignmentCenter;
titleView.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
titleView.text = self.title;
titleView.userInteractionEnabled = YES;
UITapGestureRecognizer *tgr =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(titleViewWasTapped:)];
tgr.numberOfTapsRequired = 1;
tgr.numberOfTouchesRequired = 1;
tgr.delegate = self;
[titleView addGestureRecognizer:tgr];
[tgr release];
self.navigationItem.titleView = titleView;
[titleView release];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
// This method is needed because the navigation bar with back
// buttons will swallow touch events
return (gestureRecognizer.view == self.navigationItem.titleView);
}
然后像往常一样使用手势识别器
- (void)titleViewWasTapped:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateRecognized) {
return;
}
...
}