我的应用程序中有自定义视图,可以由用户滚动.但是,此视图不会从UIScrollView继承.现在我希望用户能够将此视图滚动到顶部,就像任何其他可滚动视图允许的那样.我认为没有直接的方法可以做到这一点.
Google提出了一个解决方案:http://cocoawithlove.com/2009/05/intercepting-status-bar-touches-on.html这不再适用于iOS 4.x. 那是不行的.
我有想法创建一个scrollview并将其保存在某个地方,只是为了捕获它的通知然后将它们转发给我的控件.这不是解决我的问题的好方法,所以我正在寻找"更清洁"的解决方案.我喜欢前面提到的UIApplication子类链接的一般方法.但是什么API可以给我可靠的信息?
有什么想法,帮助等......?
编辑:我不喜欢我当前解决方案的另一件事是它只有在当前视图没有任何滚动视图时才有效.滚动到顶部的手势只有在周围只有一个滚动视图时才有效.只要将虚拟添加到具有另一个滚动视图的视图(请参阅下面的详细说明),手势就会完全禁用.寻找更好解决方案的另一个原因......
Fla*_*lar 51
最后,我从这里的答案中汇总了工作解决方案.感谢你们.
在某处声明通知名称(例如AppDelegate.h):
static NSString * const kStatusBarTappedNotification = @"statusBarTappedNotification";
Run Code Online (Sandbox Code Playgroud)
将以下行添加到AppDelegate.m:
#pragma mark - Status bar touch tracking
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
CGPoint location = [[[event allTouches] anyObject] locationInView:[self window]];
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
if (CGRectContainsPoint(statusBarFrame, location)) {
[self statusBarTouchedAction];
}
}
- (void)statusBarTouchedAction {
[[NSNotificationCenter defaultCenter] postNotificationName:kStatusBarTappedNotification
object:nil];
}
Run Code Online (Sandbox Code Playgroud)
观察所需控制器中的通知(例如,在viewWillAppear中):
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarTappedAction:)
name:kStatusBarTappedNotification
object:nil];
Run Code Online (Sandbox Code Playgroud)
正确删除观察者(例如在viewDidDisappear中):
[[NSNotificationCenter defaultCenter] removeObserver:self name:kStatusBarTappedNotification object:nil];
Run Code Online (Sandbox Code Playgroud)
实现通知处理回调:
- (void)statusBarTappedAction:(NSNotification*)notification {
NSLog(@"StatusBar tapped");
//handle StatusBar tap here.
}
Run Code Online (Sandbox Code Playgroud)
希望它会有所帮助.
Swift 3更新
测试并适用于iOS 9+.
在某处声明通知名称:
let statusBarTappedNotification = Notification(name: Notification.Name(rawValue: "statusBarTappedNotification"))
Run Code Online (Sandbox Code Playgroud)
跟踪状态栏触摸和发布通知.将以下行添加到AppDelegate.swift:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let statusBarRect = UIApplication.shared.statusBarFrame
guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return }
if statusBarRect.contains(touchPoint) {
NotificationCenter.default.post(statusBarTappedNotification)
}
}
Run Code Online (Sandbox Code Playgroud)
必要时观察通知:
NotificationCenter.default.addObserver(forName: statusBarTappedNotification.name, object: .none, queue: .none) { _ in
print("status bar tapped")
}
Run Code Online (Sandbox Code Playgroud)
Max*_*ann 31
所以这是我目前的解决方案,效果非常好.但请带上其他想法,因为我不喜欢它...
contentSize大于边界contentOffset通过始终返回NO,滚动视图永远不会向上滚动,只要用户点击状态栏,就会收到通知.但问题是,这不适用于"真实"内容滚动视图.(见问题)
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
// Do your action here
return NO;
}
Run Code Online (Sandbox Code Playgroud)
小智 15
将此添加到AppDelegate.swift将执行您想要的操作:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
super.touchesBegan(touches, withEvent: event)
let events = event!.allTouches()
let touch = events!.first
let location = touch!.locationInView(self.window)
let statusBarFrame = UIApplication.sharedApplication().statusBarFrame
if CGRectContainsPoint(statusBarFrame, location) {
NSNotificationCenter.defaultCenter().postNotificationName("statusBarSelected", object: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以根据需要订阅活动:
NSNotificationCenter.defaultCenter().addObserverForName("statusBarSelected", object: nil, queue: nil) { event in
// scroll to top of a table view
self.tableView!.setContentOffset(CGPointZero, animated: true)
}
Run Code Online (Sandbox Code Playgroud)
aml*_*szk 11
找到了一个更好的iOS7兼容解决方案:http://ruiaureliano.tumblr.com/post/37260346960/uitableview-tap-status-bar-to-scroll-up
将此方法添加到AppDelegate:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
CGPoint location = [[[event allTouches] anyObject] locationInView:[self window]];
if (CGRectContainsPoint([UIApplication sharedApplication].statusBarFrame, location)) {
NSLog(@"STATUS BAR TAPPED!");
}
}
Run Code Online (Sandbox Code Playgroud)
man*_*git 10
我通过在状态栏上添加一个清晰的UIView然后拦截触摸事件来实现这一点
首先在Application委托应用程序中:didFinishLaunchingWithOptions:添加以下两行代码:
self.window.backgroundColor = [UIColor clearColor];
self.window.windowLevel = UIWindowLevelStatusBar+1.f;
Run Code Online (Sandbox Code Playgroud)
然后在视图控制器中,您希望拦截状态栏点击(或在应用程序委托中)添加以下代码
UIView* statusBarInterceptView = [[[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame] autorelease];
statusBarInterceptView.backgroundColor = [UIColor clearColor];
UITapGestureRecognizer* tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(statusBarClicked)] autorelease];
[statusBarInterceptView addGestureRecognizer:tapRecognizer];
[[[UIApplication sharedApplication].delegate window] addSubview:statusBarInterceptView];
Run Code Online (Sandbox Code Playgroud)
在statusBarClicked选择器中,执行您需要执行的操作,在我的情况下,我向通知中心发布了通知,以便其他视图控制器可以响应状态栏点击.
小智 8
谢谢Max,您的解决方案经过多年的努力寻找后,对我有用.
有关信息:
dummyScrollView = [[UIScrollView alloc] init];
dummyScrollView.delegate = self;
[view addSubview:dummyScrollView];
[view sendSubviewToBack:dummyScrollView];
Run Code Online (Sandbox Code Playgroud)
然后
dummyScrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height+200);
// scroll it a bit, otherwise scrollViewShouldScrollToTop not called
dummyScrollView.contentOffset = CGPointMake(0, 1);
//delegate :
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView
{
// DETECTED! - do what you need to
NSLog(@"scrollViewShouldScrollToTop");
return NO;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我还有一个UIWebView,我不得不破解我在某处找到的解决方案:
- (void)webViewDidFinishLoad:(UIWebView *)wv
{
[super webViewDidFinishLoad:wv];
UIScrollView *scroller = (UIScrollView *)[[webView subviews] objectAtIndex:0];
if ([scroller respondsToSelector:@selector(setScrollEnabled:)])
scroller.scrollEnabled = NO;
}
Run Code Online (Sandbox Code Playgroud)
使用隐形UIScrollView. 在 iOS 10 和 Swift 3 上测试。
override func viewDidLoad() {
let scrollView = UIScrollView()
scrollView.bounds = view.bounds
scrollView.contentOffset.y = 1
scrollView.contentSize.height = view.bounds.height + 1
scrollView.delegate = self
view.addSubview(scrollView)
}
func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool {
debugPrint("status bar tapped")
return false
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30189 次 |
| 最近记录: |