主題 UIScrollView
iOS APP中有一個(gè)非常好用的功能,那就是當(dāng)我們?cè)跐L動(dòng)一個(gè)UIScrollView滾動(dòng)了很遠(yuǎn)很遠(yuǎn)的時(shí)候,假如我們想讓UIScrollView回到頂部,我們絕大多數(shù)人的做法就是慢慢慢慢的滾動(dòng)UIScrollView直到他回到頂部,但是iOS給我們提供了一個(gè)非常有用的功能,那就是只要我們一點(diǎn)擊屏幕上的狀態(tài)欄,就能讓UIScrollView自動(dòng)回到頂部(初始位置),其實(shí)我也是今天學(xué)到了這個(gè)知識(shí)點(diǎn)才知道了這個(gè)功能:sweat_smile::joy::joy:感謝MJ
讓UIScrollView自動(dòng)回到頂部(初始位置)的原理:要使UIScrollView滾動(dòng)到某一個(gè)位置,無非就是設(shè)置
CGPoint offect = scrollView.contentOffset;
offect.y = - scrollView.contentInset.top;
[scrollView setContentOffset:offect animated:YES];
當(dāng)控制器上只有一個(gè)UIScrollView時(shí),系統(tǒng)就會(huì)去遍歷主窗口上所有的view,當(dāng)遍歷到那個(gè)UIScrollView時(shí),就會(huì)為他設(shè)置:
CGPoint offect = scrollView.contentOffset;
offect.y = - scrollView.contentInset.top;
[scrollView setContentOffset:offect animated:YES];
當(dāng)我們一點(diǎn)擊statusBar時(shí),就會(huì)執(zhí)行上述代碼讓UIScrollView回滾到初始位置
這個(gè)功能的不足之處:
當(dāng)控制器上面只有一個(gè)UIScrollView的時(shí)候,系統(tǒng)才會(huì)為這個(gè)UIScrollView添加這個(gè)自動(dòng)回滾到頂部的功能
當(dāng)一個(gè)控制器上有多個(gè)UIScrollView時(shí),系統(tǒng)就懵了,因?yàn)樗淮_定到底要為那個(gè)UIScrollView設(shè)置這個(gè)自動(dòng)回滾到頂部的功能,這個(gè)時(shí)候就只能有我們coder明確的告訴系統(tǒng):我們要為哪個(gè)UIScrollView設(shè)置自動(dòng)回滾到頂部的功能
解決辦法:
既然系統(tǒng)不能在有多個(gè)UIScrollView的時(shí)候設(shè)置上述功能,那哥就自己來設(shè)置,問題是在眾多的UIScrollView中,我們應(yīng)該為那個(gè)UIScrollView設(shè)置這種功能呢??
答案是:我們只為顯示在用戶眼前的UIScrollView設(shè)置那個(gè)功能
1.新建一個(gè)類LXBTopWindow,我們要在里面控制window的創(chuàng)建,顯示和隱藏,我們并不會(huì)用到系統(tǒng)自帶的一個(gè)UIWindow的方法或者屬性,因此繼承自NSObject就夠了,為了調(diào)用方便,過設(shè)計(jì)為類方法
2.由于在iOS9中,所有的window都必須要有一個(gè)rootViewController,因此我們新建一個(gè)類LXBTopViewController讓他作為window的rootViewController
3.遍歷window上的所有UIScrollView,為滿足實(shí)際要求的UIScrollView設(shè)置回滾到初始位置的功能
Paste_Image.png
Paste_Image.png
Paste_Image.png
大家都知道自iOS7之后,statusBar的樣式是交給控制器來管理的,現(xiàn)在我們?cè)趕tatusBar上蓋了一個(gè)window,系統(tǒng)就會(huì)認(rèn)為statusBar既然已經(jīng)看不見了,就沒必要多此一舉地在用控制器去控制statusBar的樣式,因此控制器中控制statusBar樣式的代碼將會(huì)失效
失效代碼如下:
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
解決辦法:
1.既然這個(gè)問題是window引起的,那么自然可以從window下手,window一顯示出來,控制器中控制statusBar樣式的代碼就要失效,因此解決之道就是讓window隱藏就可以了
2.自iOS7之后,statusBar的樣式是交給控制器來管理的,但是在iOS7以前statusBar的樣式是由UIApplication來管理的,既然window一顯示出來,控制器中控制statusBar樣式的代碼就要失效,那么我們可不可以重新把statusBar樣式交給UIApplication來管理呢?? 你控制器失效就失效,哥把statusBar的樣式重新交給UIApplication來管理
答案是:YES,我們可以把statusBar的樣式重新交給UIApplication來管理,只需要在Info.plist文件中添加如下字典:
Paste_Image.png
這樣statusBar的樣式就會(huì)被UIApplication來管理了,我們可以通過:
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
去控制statusBar的樣式,值得注意的是,由于此時(shí)我們對(duì)statusBar的操作是應(yīng)用級(jí)別的,因此整個(gè)應(yīng)用程序中的statusBar的樣式都被修改為UIStatusBarStyleLightContent,但是有的地方是不能用UIStatusBarStyleLightContent的,因此我們要在合適的地方(比如這個(gè)控制器被彈出屏幕的時(shí)候),將statusBar的樣式復(fù)原:
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
文章二:
如果在UINavigationController內(nèi)設(shè)置一個(gè)UIViewControlller里烦,而UIViewController的第一個(gè)子視圖是UIScrollView的話,UIScrollview里面所有的subView都會(huì)發(fā)生下移辞色,如圖所示
代碼為
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollView *tempScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, 320, 200)];
[tempScroll setBackgroundColor:[UIColor grayColor]];
[tempScroll setContentSize:CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height)];
[self.view addSubview:tempScroll];
UIButton *tempButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[tempButton setBackgroundColor:[UIColor redColor]];
[tempButton setTitle:@"subView A" forState:UIControlStateNormal];
[tempButton setFrame:CGRectMake(80, 0, 80, 100)];
NSLog(@"%d",tempScroll.subviews.count);
[tempScroll addSubview:tempButton];
}
經(jīng)過驗(yàn)證性的代碼圃阳,我發(fā)現(xiàn)ios7有一個(gè)機(jī)制
在navigationBar配乓,以及statusBar都顯示的情況下撮胧,Navigation的當(dāng)前VC训措,他的VC的view的子視圖樹的根部的第一個(gè)子視圖鳖宾,如果是Scrollview的話篙梢,這個(gè)scrollview的所有子視圖都會(huì)被下移64個(gè)像素顷帖。
發(fā)現(xiàn)了這個(gè)機(jī)制之后,怎么去修正呢庭猩?
修正方案有兩個(gè)
1窟她、把scrollview的所有子視圖上移64個(gè)像素。
UIView *targetView = self.view;
while (targetView.subviews.count >0 && ![targetView isKindOfClass:[UIScrollView class]]) {
targetView = [targetView.subviews objectAtIndex:0];
}
if ([targetView isKindOfClass:[UIScrollView class]]) {
NSLog(@"you are a scrollview");
CGSize tempSize = ((UIScrollView *)targetView).contentSize;
tempSize.height -= 64;
[(UIScrollView *)targetView setContentSize:tempSize];
for (UIView *subView in targetView.subviews) {
CGRect tempRect = subView.frame;
tempRect.origin.y -= 64;
[subView setFrame:tempRect];
}
}
2蔼水、把scrollView更改地位震糖,是它不是子視圖樹的根部第一個(gè)子視圖。
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *tempBackGround = [[UIView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:tempBackGround];
UIScrollView *tempScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, 320, 200)];
[tempScroll setBackgroundColor:[UIColor grayColor]];
[tempScroll setContentSize:CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height)];
[self.view addSubview:tempScroll];
UIButton *tempButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[tempButton setBackgroundColor:[UIColor redColor]];
[tempButton setTitle:@"subView A" forState:UIControlStateNormal];
[tempButton setFrame:CGRectMake(80, 0, 80, 100)];
NSLog(@"%d",tempScroll.subviews.count);
[tempScroll addSubview:tempButton];
}