iOS實現抽屜效果
抽屜效果
在iOS中很多應用都用到了抽屜效果,例如騰訊的QQ,百度貼吧…
———
1. 最終效果如下圖所示
———
2.實現步驟
1.開始啟動的時候,新建3個不同顏色的View的
1.設置3個成員屬性,記錄三種顏色的View
@property (nonatomic,weak) UIView* redView; @property (nonatomic,weak) UIView* greenView; @property (nonatomic,weak) UIView* blueView;
2.初始化3個View
- (void)setUpthreeViews { UIView *blueView = [[UIView alloc]initWithFrame:self.view.bounds]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; _blueView = blueView;UIView *greenView = [[UIView alloc]initWithFrame:self.view.bounds]; greenView.backgroundColor = [UIColor greenColor]; [self.view addSubview:greenView]; _greenView = greenView; UIView *redView = [[UIView alloc]initWithFrame:self.view.bounds]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; _redView = redView;
}</pre>
2.實現滑動的效果
1.通過-(void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event方法來獲得當前點和初始點,從而計算出偏移量,然后計算redView的frame的值:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; //獲得當前點 CGPoint currentPoint = [touch locationInView:_redView]; //獲得起點 CGPoint prePoint = [touch previousLocationInView:_redView]; //計算在x軸方向上的偏移量 CGFloat moveX = currentPoint.x - prePoint.x; //然后通過在x軸上的偏移量,計算redView的frame _redView.frame = [self framWithOffsetX:moveX]; }
假設x移到320時,y移動到60,算出每移動一點x,移動多少y
offsetY = offsetX * 600 / 320 手指每移動一點,x軸偏移量多少,y偏移多少
- 為了好看,x移動到320,距離上下的高度需要保持一致,而且有一定的比例去縮放他的尺寸。
- touchMove只能拿到之前的frame.當前的高度 = 之前的高度 * 這個比例
縮放比例:當前的高度/之前的高度 (screenH - 2 * offsetY) / screenH。
當前的寬度保持不變就行。- y值,計算比較特殊,不能直接用之前的y,加上offsetY,往左滑動,主視圖應該往下走,但是offsetX是負數,導致主視圖會往上走。所以需要判斷是左滑還是右滑
- (CGRect)framWithOffsetX:(CGFloat)offsetX { //計算在y軸方向上的偏移量 CGFloat offsetY = offsetX/SCREENWIDTH MAXYOFFSET; //根據y方向的偏移量計算縮放比例 CGFloat scale = (SCREENHEIGHT - 2offsetY)/SCREENHEIGHT; //如果x < 0表示左滑 if (_redView.frame.origin.x < 0) { scale = (SCREENHEIGHT + 2*offsetY)/SCREENHEIGHT; }CGRect frame = _redView.frame; //計算滑動之后的frame CGFloat height = frame.size.height*scale; CGFloat width = frame.size.width; CGFloat x = frame.origin.x + offsetX; CGFloat y = (SCREENHEIGHT- height)* 0.5; return CGRectMake(x, y, width, height);
}</pre>
2.通過KVO來監聽redView的frame的變化,從而判斷redView是左滑還是右滑。往左移動,顯示右邊,隱藏左邊 往右移動,顯示左邊,隱藏右邊- (void)viewDidLoad { [super viewDidLoad]; [self setUpthreeViews];// 利用KVO時刻監聽_redView.frame改變 // Observer:誰需要觀察 // KeyPath:監聽的屬性名稱 // options: NSKeyValueObservingOptionNew監聽這個屬性新值 [_redView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}
// 只要監聽的屬性有新值的時候,只要redView.frame一改變就會調用
- (void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void *)context
{
if (self.redView.frame.origin.x > 0) {
} else if(self.redView.frame.origin.x < 0){_greenView.hidden = NO;
} }_greenView.hidden = YES;
// 當對象銷毀的時候,一定要移除觀察者
- (void)dealloc
{
[_redView removeObserver:self forKeyPath:@"frame"];
}</pre>
3.設置觸摸結束的時候,redView的frame。如果redView側滑沒有到屏幕的一半,則自動返回到初始位置。如果超過屏幕的一半,則停留在一個新的位置- (void)touchesEnded:(NSSet )touches withEvent:(UIEvent )event { CGFloat xPos = _redView.frame.origin.x; //大于屏幕的一半進入新的位置 if (xPos > SCREENWIDTH*0.5) {
} //小于屏幕的一半,大于屏幕負一半的時候,則恢復到初始狀態 if (xPos < SCREENWIDTH0.5 && xPos > -SCREENWIDTH0.5) {[UIView animateWithDuration:0.5 animations:^{ self.redView.frame = [self framWithBigThanX:ENDRIGHTX]; }]; return ;
} //xPos < -SCREENWIDTH*0.5的時候,進入新的位置 [UIView animateWithDuration:0.5 animations:^{[UIView animateWithDuration:0.5 animations:^{ self.redView.frame = [UIScreen mainScreen].bounds; }]; return ;
}];self.redView.frame = [self framWithSmallThanX:ENDLEFTX];
}
(CGRect)framWithBigThanX:(CGFloat)offsetX {
CGFloat offsetY = offsetX/SCREENWIDTH MAXYOFFSET; CGFloat scale = (SCREENHEIGHT - 2offsetY)/SCREENHEIGHT;
CGFloat height = SCREENHEIGHTscale; CGFloat width = SCREENWIDTH; CGFloat x = offsetX; CGFloat y = (SCREENHEIGHT- height) 0.5;
return CGRectMake(x, y, width, height); }
(CGRect)framWithSmallThanX:(CGFloat)offsetX { CGFloat offsetY = offsetX/SCREENWIDTH MAXYOFFSET; CGFloat scale = (SCREENHEIGHT + 2offsetY)/SCREENHEIGHT;
CGFloat height = SCREENHEIGHTscale; CGFloat width = SCREENWIDTH; CGFloat x = offsetX; CGFloat y = (SCREENHEIGHT- height) 0.5;
return CGRectMake(x, y, width, height); }</pre>