UIScrollView、控件懸停、頂部圖下拉放大效果、UITouch事件
UIScrollView的基本屬性
- 超出UIScrollView邊框的內容會被自動隱藏
- contentSize
- 設置scrollView的contentSize屬性,告訴UIScrollView所有內容的尺寸,也就是告訴它滾動范圍(最多能滾多遠)
- UIScrollView無法滾動的可能原因
- 沒有設置contentSize
- scrollEnabled = NO;
- 禁止了觸摸事件:userInteractionEnabled = NO
- 如果想要禁止某個方向的滾動,那么就可以直接設置這個方向的contentSize為0
eg:
// 禁止水平方向上滾動
self.scrollView.contentSize = CGSizeMake(0, 500);
contentOffset:(偏移量)
- 記錄UIScrollView滾動的位置,也就是內容的左上角和scrollView自身左上角X\Y的差值
- 對于X\Y值,如果內容往左上方滾動,X\Y都是增加,如果內容往右下方滾動,X\Y都是減少
eg:
- 對于X\Y值,如果內容往左上方滾動,X\Y都是增加,如果內容往右下方滾動,X\Y都是減少
// 往下移動64
self.scrollView.contentOffset = CGPointMake(0, -64);
OC語法細節:OC不允許直接修改結構體對象的屬性成員變量
contentInset:內邊距
- 這個屬性能夠在UIScrollView的四周增加額外的滾動區域,一般用來避免scrollView的內容被其他控件擋住(比如不被導航條擋住)
eg:
// 頂部多出64的內邊距
self.scrollView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
UIScrollView的其他屬性
- BOOL bounces
- 設置UIScrollView是否需要彈簧效果
- BOOL scrollEnabled
- 設置UIScrollView是否能滾動
- BOOL showHorizontalScrollIndicator
- 是否顯示水平滾動條
- BOOL showsVerticalScrollIndicator
- 是否顯示垂直滾動條
- BOOL pagingEnabled
- 是否分頁
注意
- 是否分頁
iOS7以后,導航控制器會為其中的scrollView的頂部自動添加64的內邊距,如果想去掉,可以通過下列屬性去掉
tabBarController為間隔區域的bottom添加49
取消自動添加額外滾動區域
self.automaticallyAdjustsScrollViewInsets = NO;
UIScrollView的代理方法
使用方法
首先準守<UIScrollViewDelegate>協議
設置代理
實現代理方法
注意
如果其他類(A類)成為該類中UIScrollView的代理的話,需要將 A類設成Strong,然后它成為當前類中scrollView的代理
常用代理方法為
/**
* 滾動的時候調用
*/
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
}
/**
* 即將開始拖拽的時候調用
*/
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
}
/**
* 結束拖拽的時候調用
*/
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
}
/**
* (減速完畢)停止滾動的時候調用
*/
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
}
scrollView實現內容縮放
// 最大縮放比例
self.scrollView.maximumZoomScale = 2.0;
// 最小縮放比例
self.scrollView.minimumZoomScale = 0.2;
// 同時實現代理方法
// 返回要縮放的內容控件,注意,該內容控件必須是scrollView的子控件
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
// 這個方式是內容縮放的時候調用,通過在該方法中調節內容控件的frame可以使縮放的時候內容控件始終處于scrollView的正中間
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
}
其他方法
// 將scrollView中的所有子控件都執行removeFromSuperview方法
[scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
ScrollView內部子控件添加約束的注意點
子控件的尺寸不能通過UIScrollView來計算,可以考慮通過以下方式計算
可以設置尺寸為固定值
可以相對于UIScrollView以外的其他控件來計算尺寸
UIScrollView的frame應該通過子控件以外的其他控件來計算
UIScrollView的contentSize的尺寸是通過子控件來計算的
根據子控件的尺寸以及子控件與UIScrollView之間的間距
ScrollView的一些特效效果
控件懸停效果
當scrollView往上拖拽到某一個位置的時候,控件(testView)懸停到某一個位置,當scrollView往下拉的時候,該控件(testView)又隨著scrollView一起移動
實現思路:
當往上拖拽到一定位置的時候(通過計算偏移量來判斷),讓該控件(testView)添加到self.view上,并設置該控件(testView)的frame固定到該位置,當scrollView再次往回拖拽到該位置的時候,再讓該控件(testView)再添加到scrollView上,成為scrollView的子控件
頂部圖片下拉放大效果
當scrollView往下拖拽的時候,讓頂部的imageView按比例放大
實現思路:
當scrollView往下拖拽的時候,通過偏移量來修改頂部imageView的transform(縮放的transform)。
eg:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat imageH = self.imageView.frame.size.height;
CGFloat offsetY = scrollView.contentOffset.y;
// 該判斷是實現scrollView內部的子控件懸停效果
if (offsetY >= imageH) {
// 將紅色控件添加到控制器的view中,設置Y值為0
CGRect redF = self.redView.frame;
redF.origin.y = 0;
self.redView.frame = redF;
[self.view addSubview:self.redView];
}else{
// 將紅色控件添加到scrollView中,設置Y值為圖片的高度
CGRect redF = self.redView.frame;
redF.origin.y = 140;
self.redView.frame = redF;
[self.scrollView addSubview:self.redView];
}
// 實現下拉放大頂部圖片效果
CGFloat scale = 1 - (offsetY / 70);
scale = (scale >= 1) ? scale : 1;
self.imageView.transform = CGAffineTransformMakeScale(scale, scale);
}
分頁指示器UIPageControl
UIPageControl
顏色指示器
tintColor: 其他頁面的指示顏色
currentPageIndicatorTintColor:當前頁顏色
numberOfPages:總共有多少頁
注意 一定不要將UIPageControl放到UIScrollView里,這樣的話UIScrollView的內容拖動的時候容易把UIPageControl拖走
pageControl.hidesForSinglePage = YES;
當只有一頁時自動隱藏pageControl
關于UIScrollView不能響應UITouch事件的解決辦法
原因是:UIView的touch事件被UIScrollView捕獲了。
解決辦法:讓UIScrollView將事件傳遞過去。于是最簡單的解決辦法就是加一個UIScrollView的category。這樣每個用到UIScrollView的地方只要導入這個category就可以直接響應相關的touch事件了。
#import "UIScrollView+UITouch.h"
@implementation UIScrollView (UITouch)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self nextResponder] touchesBegan:touches withEvent:event];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[[self nextResponder] touchesMoved:touches withEvent:event];
[super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self nextResponder] touchesEnded:touches withEvent:event];
[super touchesEnded:touches withEvent:event];
}
@end