侧滑的探究之路:

只是粗略的研究了侧滑的功能,界面做的很粗糙,随便看看效果图吧:

            

左图是滑动之前,右图是滑动之后。

1、实现功能:

           该侧滑功能实现的是视图控制器之间的侧滑。利用pan手势将当前视图控制器向左拖动即可把视图控制器拖拽成右图的效果。利用pan手势可以拖拽回去,也可以点击右侧的视图控制器将其位置还原成左图。

只是粗略的研究了侧滑的功能,界面做的很粗糙,随便看看效果图吧:

2、部分实现代码:

在SliderViewController.h中

@interface SliderViewController : UIViewController<UIGestureRecognizerDelegate>
//这个可滑动的视图控制器上视图控制器属性,即左滑时出现的LeftViewController,右滑时出现的RightVIewCOntroller和当前显示的MainViewController
@property (nonatomic,strong) UIViewController *leftVC;
@property (nonatomic,strong) UIViewController *mainVC;

//将视图控制器存放在字典中
@property(nonatomic,strong)NSMutableDictionary *controllersDict;

@property (nonatomic,assign) float leftContentOffset;//向左滑得偏移量
@property (nonatomic,assign) float leftContentViewOffset;

@property (nonatomic,assign) float leftContentScale;//初始化缩小的属性
@property(nonatomic,assign)float LeftSJudgeOffset;//如果pan手势拖拽视图控制器的偏移量大于100则该控制器会自动归位到想要拖拽的位置,如果小于100则恢复原位置
@property(nonatomic,assign)float LeftSCloseDuration;//初始化拖拽的动画时间
@property(nonatomic,assign)BOOL canShowLeft;

@property (nonatomic, copy) void(^changeLeftView)(CGFloat sca, CGFloat transX);

+ (SliderViewController *)sharedSliderViewController;

在SliderViewController.m中

typedef NS_ENUM(NSInteger, RMoveDirection) {
    RMoveDirectionLeft = 0,
    RMoveDirectionRight
};

@interface SliderViewController ()
{
    UIView *_mainContentView;
    //左侧的视图
    UIView *_leftSideView;
    //承载视图的字典
    NSMutableDictionary *_controllersDict;
    //单击事件
    UITapGestureRecognizer *_tapGestureRec;
    //滑动手势
    UIPanGestureRecognizer *_panGestureRec;
    
    BOOL showingLeft;

}
@end

@implementation SliderViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}


- (id)init{
    if (self = [super init]){
    //初始化属性
        _leftContentOffset=160;
        _leftContentScale=0.85;
        _LeftSJudgeOffset=100;
        _LeftSCloseDuration=0.3;
        _canShowLeft=YES;
    }
    
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"image"]];
    
    //隐藏导航栏
    self.navigationController.navigationBarHidden = YES;
    _controllersDict = [[NSMutableDictionary alloc] init];
    //创建当前视图控制器的子视图,即_mainContentView,_leftSideView
    [self initSubView];

    [self initChildControllers:_leftVC];
    //主视图切换不同的界面,将模型传给当前显示的控制器,如果主视图不存在,即第一次创建主视图,将主视图中的class传过来,否则直接将名为MainViewController的模型传过来
    [self showContentControllerWithModel:_mainVC != nil?NSStringFromClass([_mainVC class]):@"MainViewController"];
    
    //创建单击手势,单击关闭侧滑
    _tapGestureRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeSideBar:)];
    //设置手势的代理
    _tapGestureRec.delegate = self;
    [self.view addGestureRecognizer:_tapGestureRec];
    //关闭单击事件
    _tapGestureRec.enabled = NO;
    
    //创建滑动手势,滑动视图
    _panGestureRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveViewWithGesture:)];
    [self.view addGestureRecognizer:_panGestureRec];

    
}

+ (SliderViewController *)sharedSliderViewController
{
    static SliderViewController *sharedVC;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedVC = [[SliderViewController alloc] init];
    });
    return sharedVC;
}

- (void)initSubView
{
    //左侧视图
    _leftSideView = [[UIView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:_leftSideView];
    //主视图
    _mainContentView = [[UIView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:_mainContentView];
}

- (void)initChildControllers:(UIViewController *)leftVC
{
    //如果_canShowLeft属性为YES(表示可以显示左侧视图)并且左侧视图也存在的情况下,将左侧的控制器加到当前的控制器上
    if (_canShowLeft && leftVC != nil) {
        [self addChildViewController:leftVC];
        leftVC.view.frame = CGRectMake(0, 0, leftVC.view.frame.size.width, leftVC.view.frame.size.height);
        [_leftSideView addSubview:leftVC.view];
    }
}

#pragma mark - 主视图切换不同界面的方法
- (void)showContentControllerWithModel:(NSString *)className
{
    //将要名为className的模型从字典中取出来
    UIViewController *controller = _controllersDict[className];
    //如果字典中没有这个对应的模型
    if (!controller)
    {
        //创建和这个名字对应的类,然后加到字典中
        Class c = NSClassFromString(className);
        
#if __has_feature(objc_arc)//如果是arc的环境,则不需要release,否则需要release
        controller = [[c alloc] init];
#else
        controller = [[[c alloc] init] autorelease];
#endif
        [_controllersDict setObject:controller forKey:className];
    }
    controller.view.frame = _mainContentView.frame;
    [_mainContentView addSubview:controller.view];
    //使这个视图成为主视图
    self.mainVC = controller;
}
#pragma mark -手势事件
- (void)closeSideBar:(UITapGestureRecognizer *)tap
{//无论你对当前视图做了怎么样的动画效果,使用CGAffineTransformIdentity可以为你还原
    CGAffineTransform originalT = CGAffineTransformIdentity;
    //设置当前视图的动画时间
    [UIView animateWithDuration:_LeftSCloseDuration animations:^{
        //将视图的动画效果还原
        _mainContentView.transform = originalT;
    } completion:^(BOOL finished) {
        //关闭了左侧视图之后单击事件不可用
        _tapGestureRec.enabled = NO;
        showingLeft = NO;
//        showingRight = NO;
        //开启主视图的可点击事件
        _mainVC.view.userInteractionEnabled = YES;
    
    }];
    
}

- (void)moveViewWithGesture:(UIPanGestureRecognizer *)pan
{
    //视图沿x轴的偏移量
    static CGFloat currentTranslateX;
    if (pan.state == UIGestureRecognizerStateBegan) {
        //开始移动时主视图的偏移量
        currentTranslateX = _mainContentView.transform.tx;
    }else if (pan.state == UIGestureRecognizerStateChanged)
    {
        //translationInView方法在这返回的是主视图_mainContentView沿x轴的偏移量
        CGFloat transX = [pan translationInView:_mainContentView].x;
        //移动时主视图的偏移量随着位移的改变而增加
        transX = transX +currentTranslateX;
        CGFloat sca=0;

        //主视图沿x轴的位移
        CGFloat ltransX = (transX - _leftContentOffset)/_leftContentOffset * _leftContentViewOffset;
        CGFloat lsca = 1;
        //transX>0向右滑动
        if (transX > 0)
        {
            if (!_canShowLeft||_leftVC==nil) {
                return;
            }
            //向右滑动时
            if (_mainContentView.frame.origin.x < _leftContentOffset)
            {
                //缩小
                sca = 1 - (_mainContentView.frame.origin.x/_leftContentOffset) * (1-_leftContentScale);
                lsca = 1 - sca + _leftContentScale;
            }
            else
            {//向左滑动放大
                sca = _leftContentScale;
                lsca = 1;
                
                ltransX = 0;
            }
            //将参数传给AppDelegate
            self.changeLeftView(lsca, ltransX);
        }
        CGAffineTransform transS = CGAffineTransformMakeScale(sca, sca);
        CGAffineTransform transT = CGAffineTransformMakeTranslation(transX, 0);
        CGAffineTransform conT = CGAffineTransformConcat(transT, transS);
        _mainContentView.transform = conT;
        
    }else if (pan.state == UIGestureRecognizerStateEnded)
    {
        CGFloat panX = [pan translationInView:_mainContentView].x;
        NSLog(@"panX-----------:%f",panX);
        CGFloat finalX = currentTranslateX + panX;
        NSLog(@"finalX---------:%f",finalX);
        //判断结束滑动时主视图的位移是否大于_LeftSJudgeOffset(100),如果大于则滑动成功,否则滑回去
        if (finalX > _LeftSJudgeOffset)
        {
            if (!_canShowLeft||_leftVC==nil) {
                return;
            }
            
            CGAffineTransform conT = [self transformWithDirection:RMoveDirectionRight];
            [UIView beginAnimations:nil context:nil];
            _mainContentView.transform = conT;
            [UIView commitAnimations];
            
            showingLeft=YES;
            _mainVC.view.userInteractionEnabled=NO;
            
            _tapGestureRec.enabled = YES;
            
            [self showLeft:YES];
            
            return;
        }
        else
        {
            CGAffineTransform oriT = CGAffineTransformIdentity;
            [UIView beginAnimations:nil context:nil];
            _mainContentView.transform = oriT;
            [UIView commitAnimations];
            
            [self showLeft:NO];
            showingLeft=NO;
            _mainVC.view.userInteractionEnabled=YES;
            _tapGestureRec.enabled = NO;
        }


    }
}
- (void)showLeft:(BOOL)bShow
{
    if (bShow)
    {
        [UIView beginAnimations:nil context:nil];
        self.changeLeftView(1, 0);
        [UIView commitAnimations];
    }else
    {
        [UIView beginAnimations:nil context:nil];
        self.changeLeftView(_leftContentScale, -_leftContentViewOffset);
        [UIView commitAnimations];
    }
}

- (CGAffineTransform)transformWithDirection:(RMoveDirection)direction
{
    CGFloat translateX = _leftContentOffset;
    CGFloat transcale = _leftContentScale;
    
    CGAffineTransform transT = CGAffineTransformMakeTranslation(translateX, 0);
    CGAffineTransform scaleT = CGAffineTransformMakeScale(transcale, transcale);
    CGAffineTransform conT = CGAffineTransformConcat(transT, scaleT);
    
    return conT;
}


<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">在AppDelegate.m中</span>

 //将滑动视图导航控制器作为根视图,SliderViewController是个单例。
    SliderViewController *SliderVC = [SliderViewController sharedSliderViewController];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:SliderVC];
    self.window.rootViewController = nav;
    
    //使滑动视图控制器持有两个视图控制器
    LeftViewController *leftVC = [[LeftViewController alloc] init];
    SliderVC.leftVC = leftVC;
    MainViewController *mainVC = [[MainViewController alloc] init];
    SliderVC.mainVC = mainVC;
    
    SliderVC.leftContentOffset = 275;
    SliderVC.leftContentViewOffset = 90;
    
    SliderVC.leftContentScale = 0.77;
    SliderVC.LeftSJudgeOffset = 160;
    
    SliderVC.changeLeftView = ^(CGFloat sca,CGFloat transX){
        //缩小sca倍
        CGAffineTransform ltransS = CGAffineTransformMakeScale(sca, sca);
        //沿x轴平移transX
        CGAffineTransform ltransT = CGAffineTransformMakeTranslation(transX, 0);
        //组合ltransT和ltransS的变化效果,即缩小又平移
        CGAffineTransform lconT = CGAffineTransformConcat(ltransT, ltransS);
        leftVC.contentView.transform = lconT;     
    };

主视图控制器中的tableView在这里就不写出来了。

如果有错误的地方欢迎大家指教。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值