先上效果圖把:
項目有這個需求,之前是別人做的效果不太好利耍,后來需要重寫,但還是不是我負責盔粹,但是那段時間不算很忙隘梨,也用自己的思路嘗試著寫了一下,實現(xiàn)的效果很差舷嗡。
現(xiàn)在這個完成效果是項目組的主程寫的轴猎,最近有空看了一下代碼,然后自己模仿著重寫了一下进萄。
看完代碼捻脖,其實實現(xiàn)思路很簡單
1.在控制器中添加三個UIView,分別用來放三個子控制器垮斯;
2.為view添加panGesture,在手勢的delegate中獲取位移來處理界面變化郎仆;
3.利用UIView的transform屬性來實現(xiàn)界面的變化和移動。
關(guān)于transform屬性,是用矩陣乘法對界面進行位移兜蠕,旋轉(zhuǎn)扰肌,放大縮小等,其實可以簡單理解為基于參考坐標系做出一系列變化:
CGAffineTransformRotate // 旋轉(zhuǎn)
CGAffineTransformScale // 放大縮小
CGAffineTransformTranslate // 位移
基本思路就是這樣熊杨,接下來是具體實現(xiàn):
1.初始化方法:
- (instancetype)initWithMainViewController:(UIViewController *)mainVC
leftViewController:(UIViewController *)leftVC
rightViewController:(UIViewController *)rightVC
{
self = [super init];
if (self) {
[self prepare];
self.mainViewController = mainVC;
self.leftViewController = leftVC;
self.rightViewController = rightVC;
}
return self;
}
2.初始化界面:
為控制器添加_leftContainerView,_rightContainerView及_mainContainerView,在leftViewController的setter方法中做一些設(shè)置曙旭,配置界面的默認位置及大小等:
- (void)setLeftViewController:(UIViewController *)leftViewController
{
if (!leftViewController) {
return;
}
_canShowLeft = YES;
_leftViewController = leftViewController;
_leftViewController.view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
[self addChildViewController:leftViewController];
[_leftContainerView addSubview:leftViewController.view];
_leftContainerView.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, -leftShowWidth, 0);
_leftContainerView.transform = CGAffineTransformScale(_leftContainerView.transform, leftScale, leftScale);
}
此處使用的參數(shù)為預(yù)先設(shè)置好的,可以修改leftScale或rightScale晶府,改變?yōu)閳D1或圖3的顯示效果:
#pragma mark ---------- left config -----------
static CGFloat const leftShowWidth = 240.f;
static CGFloat const leftScale = 0.8f; // 縮放比例
static CGFloat const leftDragbleWidth = 80.f; // 左側(cè)可拖動寬度
static CGFloat const leftMinDragLength = 100.f; //觸發(fā)所需要拖動的最短距離
3.做好界面默認配置以后桂躏,需要的就是添加Pan手勢,并做處理川陆,
此處只表述思路剂习,實際代碼復(fù)雜的多
- (void)panGestureHandler:(UIPanGestureRecognizer *)gesture
{
CGPoint point = [gesture locationInView:self.view];
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
{
// 記錄拖拽的起點
_startDragPoint = point;
_lastDragPoint = point;
}
break;
case UIGestureRecognizerStateChanged:
{
CGFloat move_length = point.x - _lastDragPoint.x;
CGFloat scale = 1;
_lastDragPoint = point;
// 進行判斷是呼出哪邊的界面 此處寫呼出左側(cè)界面
scale = 1-(move_length/leftShowWidth)*(1-leftScale);
// 根據(jù)拖拽移動的距離進行界面的變化
_mainContainerView.transform = CGAffineTransformTranslate(_mainContainerView.transform, move_length, 0);
_mainContainerView.transform = CGAffineTransformScale(_mainContainerView.transform, scale, scale);
CGFloat left_scale = 1+(move_length/leftShowWidth)*(1-leftScale);
_leftContainerView.transform = CGAffineTransformTranslate(_leftContainerView.transform, move_length, 0);
_leftContainerView.transform = CGAffineTransformScale(_leftContainerView.transform, left_scale, left_scale);
}
break;
case UIGestureRecognizerStateEnded:
{
CGFloat move_length = fabs(point.x - _startDragPoint.x);
// 判斷拖拽距離是否足夠顯示或隱藏界面
// 此處只作為例子,以左側(cè)界面為例子
if (move_length>leftMinDragLength) {
if (_isLeftShow) {
[self hideLeft];
}else{
[self showLeft];
}
}else{
if (_isLeftShow) {
[self showLeft];
}else{
[self hideLeft];
}
}
break;
上述代碼中较沪,進行界面變化前還需增加判斷鳞绕,何時停止變化。
在show和hide方法中尸曼,需要進行動畫duration的計算们何,然后進行界面變化。剩下的基本就是在兩個leftController和rightController中進行界面布局了控轿。
由于使用了多個controller冤竹,所以leftController和rightController的跳轉(zhuǎn)操作要交由mainController的navigationController來進行拂封,代碼中提供了屬性以供跳轉(zhuǎn),若有不同需求鹦蠕,需要重寫此屬性的getter方法冒签。
@property (nonatomic, strong, readonly) UINavigationController *sliderNavigationController;
基本思路就是這樣,比較復(fù)雜的基本上是界面位移縮放比例的換算钟病,需要在GestureChanged狀態(tài)中進行處理镣衡。
若有BUG或改進方法,歡迎留言或給我發(fā)郵件档悠。