UIScrollView回滾到頂部解決方案
- 根據系統的不同分成兩種情況
- iOS9之前,如果頁面上有兩個UIScroolView,那么點擊導航欄將沒有反應
- iOS9之后(包括iOS9),頁面內多個UIScrollView,點擊導航欄將根據不同情況,回滾不同的UIScroolView
iOS9之前的處理方案
- 其實現在寫這個方案意義不是很大,iOS11正式版很快就要發布了,對于系統的適配,iOS9-11就可以了,iOS8基本上可以放棄了
- 先說一下思路
- 需要攔截點擊導航欄操作-使用UIWindow,在導航欄上面覆蓋一層沒有顏色的window,級別設置到最高
- 攔截點擊操作之后,遍歷keyWindow上所有的子控件
- 判斷這個子控件是否是UIScrollView
- 判斷這個子控件是否顯示在keyWindow上
- 都滿足之后將找到的子控件的contentOffset的y值設置為0即可
- 這種方式的不足之處:如果有兩個UIScrollView都在屏幕上面,都是垂直滾動,那么點擊之后,兩個都會回到頂部,想要解決個問題,就需要進一步判斷是哪一個UIScrollView
// 頂部的window,覆蓋在狀態欄上面,點擊之后將window上顯示的scrollView滑動到頂部
#import <Foundation/Foundation.h>
@interface YWTopWindow : NSObject
+ (void)show;
+ (void)hide;
@end
#import "YWTopWindow.h"
#import "UIView+YWExtension.h"
@implementation YWTopWindow
static UIWindow *window_;
+ (void)initialize
{
window_ = [[UIWindow alloc] init];
window_.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 20);
window_.backgroundColor = [UIColor clearColor];
// 將級別設置為最高,這樣就能蓋住狀態欄
window_.windowLevel = UIWindowLevelAlert;
[window_ addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(windowClick)]];
}
+ (void)show
{
// iOS9之前,可以直接寫window_.hidden = NO;
// 在iOS9之后,直接寫會報錯,大概的意思就是:在程序啟動結束后,window需要有一個根控制器
// Application windows are expected to have a root view controller at the end of application launch
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
window_.hidden = NO;
});
}
+ (void)hide
{
window_.hidden = YES;
}
/**
窗口點擊
*/
+ (void)windowClick
{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[self searchScrollViewInView:window];
}
+ (void)searchScrollViewInView:(UIView *)superview
{
for (UIScrollView *subView in superview.subviews) {
// 如果是UIScrollView,滾動到最頂部
if([subView isKindOfClass:[UIScrollView class]] && subView.isShowingOnKeyWindow){
CGPoint offset = subView.contentOffset;
offset.y = - subView.contentInset.top;
[subView setContentOffset:offset animated:YES];
}
// 不是UIScrollView或者不是顯示在keyWindow上,繼續尋找
[self searchScrollViewInView:subView];
}
}
@end
// 寫在UIView的分類中的方法
// 判斷一個控件是否顯示在主窗口上面
- (BOOL)isShowingOnKeyWindow
{
// 主窗口
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
// 以主窗口左上角為坐標原點,計算self的矩形框
CGRect newFrame = [keyWindow convertRect:self.frame fromView:self.superview];
CGRect winBounds = keyWindow.bounds;
// 主窗口的bounds和self的矩形框是否有重疊
BOOL intersects = CGRectIntersectsRect(newFrame, winBounds);
return !self.isHidden && self.alpha > 0.01 && self.window == keyWindow && intersects;
}
iOS9之后(包含iOS9)
- 頁面上兩個UIScrollView,類似今日頭條的布局,第一個橫向滑動,第二個也是橫向滑動,但是里面有好多UITableView
- 這種可以不用管,系統會自動將當前顯示的UITableView滑動到頂部
- 頁面上有兩個UIScrollView,都是垂直滾動,兩個都顯示在頁面上
- 左右分布,那么點擊導航欄位置在那個控件上方,滾動那個UIScrollView
- 上下分布,點擊導航欄時,上方的控件在初始位置,那么滾動下方的控件,如果上方的有滾動過,那么就會將上方的UIScrollView滾動到最上方
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。