標籤:
基本資料擷取
經過體驗,手機QQ採用的應該是線性動畫,即視圖縮放比例等隨手指在螢幕上滑動的距離以一次方程的形式變化。
提取基本資料,向右側滑達到最大幅度時:
1、 右側主視圖左邊界距離螢幕左邊界的距離占螢幕寬度的比例為:78%
2、 右側主視圖的高度占螢幕高度的比例為:77%
分步實現:
1、實現主視圖的縮放側滑;
2、實現主視圖與左視圖的聯動;
第一步,實現主視圖的縮放側滑
此前動手做時參考了一些類似的demo,發現許多是用手勢UIPanGestureRecognizer來實現的,而本文將採用UITouch。並使用以下兩個觸摸觸發事件:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
原理:
主視圖mainVC的移動和縮放:
①. 主視圖frmae的x座標 = 主視圖frmae的x座標 + 手指滑動的x軸總位移量位移量;
#pragma mark - 手指在螢幕上移動- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ if ([event touchesForView:_mainVC.view]) { // 擷取UITouch對象 UITouch *touch = [touches anyObject]; // 擷取當前點 CGPoint currentPoint = [touch locationInView:self.view]; // 擷取上一個點 CGPoint prePoint = [touch previousLocationInView:self.view]; // x軸位移量:當手指移動一點的時候,x位移多少 CGFloat offsetX = currentPoint.x - prePoint.x; // 設定當前主視圖的frame _mainVC.view.frame = [self getCurrentFrameWithOffsetX:offsetX]; // 移動漸層效果 (明 - 暗) _blackCover.alpha = (1 - _mainVC.view.frame.origin.x / RTarget); } // 判斷是拖拽 還是 點擊tap _isDraging = YES;}
②. 主視圖的縮放比例 :
// 當手指位移一點,根據X軸的位移量算出當前主視圖的frame- (CGRect)getCurrentFrameWithOffsetX:(CGFloat)offsetX{ // 擷取y軸位移量,手指每移動一點,y軸位移多少 CGFloat offsetY = offsetX * _maxOffestHight / screenWidth; // 每次移動縮小比例 CGFloat scale = (screenHeight - 2 * offsetY) / screenHeight;#if 0 if (offsetX < 0 && _mainVC.view.frame.origin.x <= 0) { // 往左邊滑動 scale = (screenH + 2 * offsetY) / screenH; }#endif // 擷取之前的frame *************** 限制成只能顯示左視圖! CGRect frame = _mainVC.view.frame; if ((frame.origin.x+offsetX) >=0 ) frame.origin.x += offsetX; else frame.origin.x = 0; frame.size.height = frame.size.height *scale; frame.size.width = frame.size.width *scale; frame.origin.y = (screenHeight - frame.size.height) / 2.0; return frame;}
/** 當手指位移一點,根據X軸的位移量算出當前主視圖的frame **/
// 擷取y軸位移量,手指每移動一點,y軸位移多少
CGFloat offsetY = offsetX * _maxOffestHight / screenWidth;
// 每次移動縮小比例
CGFloat scale = (screenHeight - 2 * offsetY) / screenHeight;
CGRect frame = _mainVC.view.frame;
… …
/** 主視圖的位置變化 和 大小縮放 **/
frame.origin.x += offsetX;
frame.size.height = frame.size.height *scale;
frame.size.width = frame.size.width *scale;
frame.origin.y = (screenHeight - frame.size.height) / 2.0;
… …
第二步,實現主視圖與左視圖的聯動
原理:
重點是找出線性關係,然後聯動可以這樣做 :
1、這是leftVC.view的縮放比例:
找出這兩點 (0.77 ,0) (1 ,screenwidth* 0.78),即(left.view的縮放比例, main.view.x座標),可得線性關係:
CGFloat leftScale = ((1 - _minSclae)/(screenWidth * _boundScale))*_mainVC.view.frame.origin.x + _minSclae; leftCX = _mainVC.view.frame.origin.x >= screenWidth * _boundScale ? self.view.center.x : leftCX;
2、這是leftVC.view的移動:
找出這兩點(self.view.center.x ,screenwidth * 0.78) (center - 80 , 0),即(螢幕中心點x的座標 ,main.view.or.x座標),可得線性關係:
CGFloat leftCX = ( _leftCenterFactor / (screenWidth * _boundScale) )*_mainVC.view.frame.origin.x + screenWidth/2 - _leftCenterFactor; leftScale = leftScale >= 1 ? 1 :leftScale;
3、最後移動和縮放:
_leftVC.view.center = CGPointMake(leftCX, self.view.center.y); _leftVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, leftScale, leftScale);
完整代碼:
/** * 開啟左視圖聯動事件 */- (void)startedLeftViewLinkage{ // 執行左視圖聯動動畫 // (self.view.center.x , screenwidth * 0.78) (center - 80 , 0) ==> (中心點x的座標 ,main.view.or.x座標),線性關係 CGFloat leftCX = ( _leftCenterFactor / (screenWidth * _boundScale) )*_mainVC.view.frame.origin.x + screenWidth/2 - _leftCenterFactor; leftCX = _mainVC.view.frame.origin.x >= screenWidth * _boundScale ? self.view.center.x : leftCX; // (0.77 , 0) (1 , screenwidth*0.78) ==》 (left.view的縮放比例, main.view.or.x座標),線性關係 CGFloat leftScale = ((1 - _minSclae)/(screenWidth * _boundScale))*_mainVC.view.frame.origin.x + _minSclae; leftScale = leftScale >= 1 ? 1 :leftScale; _leftVC.view.center = CGPointMake(leftCX, self.view.center.y); _leftVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, leftScale, leftScale);}
以上是對左視圖和主視圖的移動及縮放關係的解析,側滑的關鍵就是找准視圖之間的內在動態聯絡。按本文方法可達到高仿,實現的效果基本與手機QQ一樣。
實現“手機qq”側滑菜單 -- 吳歐