感激UIKit的坐標體系特征,使我們之花了30幾行代碼就可以重現UIScrollView的精髓,固然真實的UIScrollView要比我們所做的龐雜的多,反彈後果,動量轉動,縮小試圖,還有署理辦法,這些特征我們沒有在這裡觸及到。
起首,讓我們先來懂得一下UIKit中的坐標系是怎樣任務的。假如你只對轉動試圖的代碼完成感興致可以寧神跳過下一末節。UIKit坐標系每個View都界說了他本身的坐標體系。以下圖所示,x軸指向右方,y軸指向下方:
留意這個邏輯坐標系其實不存眷包括在個中View的寬度和高度。全部坐標系沒有界限向周圍無窮延長.我們在座標系中放置四個子View。每次色塊代表一個View:
添加View的代碼完成以下:
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 100, 100)];
redView.backgroundColor = [UIColor colorWithRed:0.815 green:0.007
blue:0.105 alpha:1];
UIView *greenView = [[UIView alloc] initWithFrame:CGRectMake(150, 160, 150, 200)];
greenView.backgroundColor = [UIColor colorWithRed:0.494 green:0.827
blue:0.129 alpha:1];
UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(40, 400, 200, 150)];
blueView.backgroundColor = [UIColor colorWithRed:0.29 green:0.564
blue:0.886 alpha:1];
UIView *yellowView = [[UIView alloc] initWithFrame:CGRectMake(100, 600, 180, 150)];
yellowView.backgroundColor = [UIColor colorWithRed:0.972 green:0.905
blue:0.109 alpha:1];
[mainView addSubview:redView];
[mainView addSubview:greenView];
[mainView addSubview:blueView];
[mainView addSubview:yellowView];
bounds
Apple關於UIView的文檔中是如許描寫bounds屬性的:
bounds矩形…描寫了該視圖在其本身坐標系中的地位和年夜小。
一個View可以被看做是界說在其地點坐標系立體上的一扇窗戶或許說是一個矩形的可視區域。View的界限注解了這個矩形可視區域的地位和年夜小。
假定我們的View寬320像素,高480像素,原點在(0,0)。那末這個View就釀成了全部坐標系立體的不雅察口,它展現的只是全部立體的一小部門。位於該View界限外的區域仍然存在,只是被隱蔽起來了。
一個View供給了其地點立體的一個不雅察口。View的bounds矩形描寫了這個可是區域的地位和年夜小。
Frame
接上去我們來試著修正bounds的原點坐標:
CGRect bounds = mainView.bounds;
bounds.origin = CGPointMake(0, 100);
mainView.bounds = bounds;
當我們把bound原點設為(0,100)後,全部畫面看起來就像如許:
修正bounds的原點就相當與在立體上挪動這個可視區域。
看起來似乎是這個View向下挪動了100像素,在這個View本身的坐標系中這確切沒錯。不外這個View真正位於屏幕上的地位(更精確的說在其父View上的地位)其實沒有轉變,由於這是由View的frame屬性決議的,它並沒有轉變:
frame矩形…界說了這個View在其父View坐標系中的地位和年夜小。
因為View的地位是絕對固定的,你可以把全部坐標立體想象成我們可以高低拖動的通明幕布,把這個View想象成我們不雅察坐標立體的窗口。調劑View的Bounds屬性就相當於拖動這個幕布,那末下方的內容就可以在我們View中被不雅察到:
修正bounds的原點坐標也相當於把全部坐標系向上拖動,由於View的frame沒由變過,所以它絕對於父View的地位沒有變更過。
其實這就是UIScrollView滑動時所產生的工作。留意從一個用戶的角度來看,他認為時這個View中的子View在挪動,其實他們的在座標系中地位(他們的frame)沒有產生過變更。
打造你的UIScrollView
一個scroll view其實不須要個中子View的坐標來使他們轉動。獨一要做的就是轉變他的bounds屬性。曉得了這一點,完成一個簡略的scroll view就沒甚麼艱苦了。我們用一個gesture recognizer來辨認用戶的拖動操作,依據用戶拖動的偏移量來轉變bounds的原點:
// CustomScrollView.h
@import UIKit;
@interface CustomScrollView : UIView
@property (nonatomic) CGSize contentSize;
@end
// CustomScrollView.m
#import "CustomScrollView.h"
@implementation CustomScrollView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self == nil) {
return nil;
}
UIPanGestureRecognizer *gestureRecognizer = [[UIPanGestureRecognizer alloc]
initWithtarget:self action:@selector(handlePanGesture:)];
[self addGestureRecognizer:gestureRecognizer];
return self;
}
- (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
CGPoint translation = [gestureRecognizer translationInView:self];
CGRect bounds = self.bounds;
// Translate the view's bounds, but do not permit values that would violate contentSize
CGFloat newBoundsOriginX = bounds.origin.x - translation.x;
CGFloat minBoundsOriginX = 0.0;
CGFloat maxBoundsOriginX = self.contentSize.width - bounds.size.width;
bounds.origin.x = fmax(minBoundsOriginX, fmin(newBoundsOriginX, maxBoundsOriginX));
CGFloat newBoundsOriginY = bounds.origin.y - translation.y;
CGFloat minBoundsOriginY = 0.0;
CGFloat maxBoundsOriginY = self.contentSize.height - bounds.size.height;
bounds.origin.y = fmax(minBoundsOriginY, fmin(newBoundsOriginY, maxBoundsOriginY));
self.bounds = bounds;
[gestureRecognizer setTranslation:CGPointZero inView:self];
}
@end
和真實的UIScrollView一樣,我們的類也有一個contentSize屬性,你必需從內部來設置這個值來指定可以轉動的區域,當我們轉變bounds的年夜小時我們要確保設置的值是有用的。
成果:
UIScrollView經常使用操作辦法整頓
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// 創立一個轉動視圖
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 64, 320, 568-64)];
// 設置署理
self.scrollView.delegate = self;
self.scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:_scrollView];
/**
* CGPoint contentOffSet 監控今朝轉動的地位
* CGSize contentSize 轉動規模年夜小(主屬性)
* UIEdgeInsets contentInset 視圖在scrollView中的地位
* BOOL directionalLockEnabled 指定控件能否只能在一個偏向上轉動
* BOOL bounces 掌握控件碰到邊框能否反彈
* BOOL alwaysBounceVertical 掌握垂直偏向碰到邊框能否反彈
* BOOL alwaysBounceHorizontal 掌握程度偏向碰到邊框能否反彈
* BOOL pagingEnabled 掌握控件能否整頁翻動
* BOOL scrollEnabled 掌握控件能否能轉動
* BOOL showsHorizontalScrollIndicator 掌握能否顯示程度偏向的轉動條
* BOOL showsVerticalScrollIndicator 掌握能否顯示垂直偏向的轉動條
* UIEdgeInsets scrollIndicatorInsets 指定轉動條在scrollerView中的地位
* UIScrollVieWindicatorStyle indicatorStyle 設定轉動條的款式
* float decelerationRate 轉變scrollerView的加速點地位
* BOOL tracking 監控以後目的能否正在被跟蹤
* BOOL dragging 監控以後目的能否正在被拖拽
* BOOL decelerating 監控以後目的能否正在加速
* BOOL delaysContentTouches 掌握視圖能否延時挪用開端轉動的辦法
* BOOL canCancelContentTouches 掌握控件能否接觸撤消touch的事宜
* float minimumZoomScale 縮放的最小比例
* float maximumZoomScale 縮放的最年夜比例
* float zoomScale 設置變更比例
* BOOL bouncesZoom 掌握縮放的時刻能否會反彈
* BOOL zooming 斷定控件的年夜小能否正在轉變
* BOOL zoomBouncing 斷定能否正在停止縮放反彈
* BOOL scrollsToTop 掌握控件轉動到頂部
*/
// 提醒用戶,在界面創立的時刻,程度轉動條或許垂直轉動條會湧現一次閃現後果
[self.scrollView FlashScrollIndicators];
// 偏移帶動畫後果
[self.scrollView setContentOffset:CGPointMake(320, 0) animated:YES];
}
#pragma mark UIScrollViewDelegate
// 只需轉動了就會觸發
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
{
}
// 開端拖拽視圖
// 當開端轉動視圖時,履行該辦法。一次有用滑動(開端滑動,滑動一小段間隔,只需手指不松開,只算一次滑動),只履行一次。
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
{
}
// 滑動視圖,當手指分開屏幕那一霎那,挪用該辦法。一次有用滑動,只履行一次。
// decelerate,指代,當我們手指分開那一瞬後,視圖能否還將持續向前轉動(一段間隔),經由測試,decelerate=YES
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
}
// 將開端降速時
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
{
}
// 轉動視圖加速完成,轉動將停滯時,挪用該辦法。一次有用滑動,只履行一次。
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
{
}
// 轉動動畫停滯時履行,代碼轉變時動身,也就是setContentOffset轉變時
// 當轉動視圖動畫完成後,挪用該辦法,假如沒有動畫,那末該辦法將不被挪用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
{
}
// 設置縮小減少的視圖,如果uiscrollview的subview , 前往將要縮放的UIView對象。要履行屢次
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView;
{
return nil;
}
// 當將要開端縮放時,履行該辦法。一次有用縮放,就只履行一次。
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
{
NSLog(@"scrollViewWillBeginZooming");
}
// 當縮放停止後,而且縮縮小小回到minimumZoomScale與maximumZoomScale之間後(我們或許會超越縮放規模),挪用該辦法。
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(double)scale;
{
}
// 假如你不是完整轉動到滾軸視圖的頂部,你可以輕點狀況欄,誰人可視的滾軸視圖會一向轉動到頂部,那是默許行動,你可以經由過程該辦法前往NO來封閉它
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView;
{
return YES;
}
// 曾經滑動到頂部
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
{
}
【經由過程UIKit坐標系來周全控制iOS中的UIScrollView組件】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!