iOS开发系列之常用框架开发集—自定义UINavitationController开发1

在实际开发过程中构建我们项目框架时为了用户体验好和个性化往往需要手势返回的功能,虽然ios7以后的系统支持这个但是系统有些不足如:支持手势返回需要ios7.0以上系统,手势非要从左边缘开始拉,触摸拉开效果不能自定义,然而我们今天就给大家开发一款支持手势返回没有系统要求(ios5.0以上),从哪里可以触摸返回可以自定义的一个导航框架。

我这个是以淘宝app的导航框架为例开发。

WHC_NavigationController.h头文件如下:

//
//  WHC_NavigationController.h
//  WHC_NavigationController
//
//  Created by 吴海超 on 15/4/13.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

#import <UIKit/UIKit.h>
#define KWHC_Nav_Main_VC_Name (@"MyTabBarVC")     //主控制器类名
#define KWHC_Nav_Touch_Back_Rate (0.4)            //触摸拖拽可以返回条件比例
#define KWHC_Nav_Pop_Form_Border (-1)             //note > 0 from border pull < 0 any where pull diatancex > 30
@interface WHC_NavigationController : UINavigationController

//单例默认用KWHC_Nav_Main_VC_Name作为主控制器
+ (instancetype)sharedInstance;

//单例自定义主控制器
+ (instancetype)sharedInstanceWithMainVC:(UIViewController*)mainVC;
@end

WHC_NavigationController.m源文件如下:

//
//  WHC_NavigationController.m
//  SideMenu
//
//  Created by 吴海超 on 15/4/13.
//  Copyright (c) 2015年 吴海超. All rights reserved.
//

#import "WHC_NavigationController.h"
#define KWHC_NAV_LEFT_VIEW_TAG (203994850)                         //左边view的tag
#define KWHC_NAV_LEFT_PUSH_VIEW_TAG (KWHC_NAV_LEFT_VIEW_TAG + 1)   //左边pushView的tag
#define KWHC_NAV_NAVBAR_TAG (KWHC_NAV_LEFT_VIEW_TAG + 2)           //导航条的tag
#define KWHC_NAV_ANIMATION_DURING (0.3)                            //pop或者push动画周期
#define KWHC_NAV_POP_VIEW_CENTERX_OFFSET (0)                       //popView中心x轴偏移 (禁止修改值)
#define KWHC_NAV_PUSH_VIEW_CENTERX_OFFSET (0)                      //pushView中心x偏移  (禁止修改值)
#define KWHC_NAV_POP_VIEW_ALPHA (0.5)                              //popview透明系数
#define KWHC_NAV_ALLOW_PULL_DISTANCE (30.0)                        //可以拉开允许的距离
@interface WHC_NavigationController ()<UINavigationControllerDelegate>{
    UIPanGestureRecognizer           *   _panGesture;              //手势
    CGFloat                              _currentTx;               //存储当前触摸x值

    NSMutableArray                   *   _snapshootList;           //快照数组
    UIView                           *   _popView;                 //弹出view
    UIView                           *   _pushView;                //压站view
    UIView                           *   _topView;                 //顶部视图
    BOOL                                 _willOpen;                //是否将要拉开
    BOOL                                 _didOpen;                 //是否已经拉开
    BOOL                                 _isTouchPop;              //是否触摸弹出
}

@end

static WHC_NavigationController * whc_navigation;

@implementation WHC_NavigationController

//单例实现
+ (instancetype)sharedInstance{
    UIViewController  * rootVC = [[NSClassFromString(KWHC_Nav_Main_VC_Name) alloc]init];
    //        UIViewController  * rootVC = [[NSClassFromString(KWHC_Side_Menu_N_Main_VC_Name) alloc]initWithNibName:KWHC_Nav_Main_VC_Name bundle:nil];
    return [WHC_NavigationController sharedInstanceWithMainVC:rootVC];
}

+ (instancetype)sharedInstanceWithMainVC:(UIViewController*)mainVC{
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        whc_navigation = [[WHC_NavigationController alloc]initWithRootViewController:mainVC];
        whc_navigation.delegate = whc_navigation;
    });
    return whc_navigation;
}
#pragma mark - initMothed

//重载父类初始化方法
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController{
    self = [super initWithRootViewController:rootViewController];
    if(self){
        [self registPanGesture:YES];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if(self != nil){
        [self registPanGesture:YES];
    }
    return self;
}

- (instancetype)init{
    self = [super init];
    if(self != nil){
        [self registPanGesture:YES];
    }
    return self;
}

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if(self){
        [self registPanGesture:YES];
    }
    return self;
}
#pragma mark - gestureMothed
//注册手势事件
- (void)registPanGesture:(BOOL)b{
    self.interactivePopGestureRecognizer.enabled = NO;
    if(b){
        if(_panGesture == nil){
            _panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)];
            [_panGesture delaysTouchesBegan];
            [self.view addGestureRecognizer:_panGesture];
        }
    }else{
        if(_panGesture != nil){
            [self.view removeGestureRecognizer:_panGesture];
            _panGesture = nil;
        }
    }
}

#pragma mark - handleGesture
- (void)handlePanGesture:(UIPanGestureRecognizer*)panGesture{

    switch (panGesture.state) {
        case UIGestureRecognizerStateBegan:{
            _currentTx = self.view.transform.tx;
        }
            break;
        case UIGestureRecognizerStateChanged:{
            CGFloat  moveDistance = [panGesture translationInView:panGesture.view].x;
            if(!_willOpen){
                if(KWHC_Nav_Pop_Form_Border < (0)){
                    if(moveDistance < KWHC_NAV_ALLOW_PULL_DISTANCE){
                        return;
                    }
                }else{
                    CGFloat touchX = [panGesture locationInView:panGesture.view].x;
                    if(touchX > KWHC_Nav_Pop_Form_Border){
                        return;
                    }
                }
            }
            CGFloat  oriX = [panGesture velocityInView:panGesture.view].x;
            CGFloat  rate = moveDistance / CGRectGetWidth(self.view.frame);
            if(oriX > 0){//open door
                [self popView];
                if(!_willOpen && _popView != nil){

                    UIView * oldPopView = [self.view.superview viewWithTag:KWHC_NAV_LEFT_VIEW_TAG];
                    if(oldPopView){
                        [oldPopView removeFromSuperview];
                    }
                    [self.view.superview insertSubview:_popView belowSubview:self.view];
                    _willOpen = YES;

                }
                if(_willOpen && moveDistance >= 0.0){

                    self.view.transform = [self initAffineTransform:moveDistance + _currentTx];
                    _popView.center = CGPointMake(KWHC_NAV_POP_VIEW_CENTERX_OFFSET + rate * CGRectGetWidth(_popView.frame) / 2.0, _popView.center.y);
                    _popView.alpha = KWHC_NAV_POP_VIEW_ALPHA * (rate + 1.0);

                }

            }else if(oriX < 0 && _willOpen && moveDistance >= 0.0){//close door

                self.view.transform = [self initAffineTransform:moveDistance + _currentTx];
                _popView.center = CGPointMake(KWHC_NAV_POP_VIEW_CENTERX_OFFSET + rate * CGRectGetWidth(_popView.frame) / 2.0, _popView.center.y);
                _popView.alpha = KWHC_NAV_POP_VIEW_ALPHA * (rate + 1.0);

            }else if(_willOpen){

                if(moveDistance < 0.0 && self.view.transform.tx > 0){
                    self.view.transform = [self initAffineTransform:0.0];
                    _popView.center = CGPointMake(KWHC_NAV_POP_VIEW_CENTERX_OFFSET, _popView.center.y);
                    _popView.alpha = KWHC_NAV_POP_VIEW_ALPHA;
                }
            }
        }
            break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded:{
            if(_willOpen){
                if(self.view.transform.tx / CGRectGetWidth(self.view.frame) < KWHC_Nav_Touch_Back_Rate){
                    [self closeLeftView:YES];
                }else{
                    [self closeLeftView:NO];
                }
            }
        }
            break;
        default:
            break;
    }
}

//偏移变换
- (CGAffineTransform)initAffineTransform:(CGFloat)x{
    return  CGAffineTransformMakeTranslation(x, 0.0);
}

//对当前控制器进行快照
- (UIImage*)snapshootNavBar:(UIViewController*)vc{

    UIGraphicsBeginImageContextWithOptions(self.view.frame.size, self.view.opaque, 0.0);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage  * snapshootImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshootImage;
}

//获取要弹出view的快照view
- (UIView*)popView{
    if(_snapshootList != nil && _snapshootList.count > 1){
        _popView = [_snapshootList lastObject];
        _popView.center = CGPointMake(KWHC_NAV_POP_VIEW_CENTERX_OFFSET, _popView.center.y);
        _popView.alpha = KWHC_NAV_POP_VIEW_ALPHA;
    }else{
        _popView = nil;
    }
    return _popView;
}

//获取已经push的快照view
- (UIView*)pushView{
    if(_snapshootList != nil && _snapshootList.count > 0){
        _pushView = [_snapshootList lastObject];
        _pushView.center = CGPointMake(KWHC_NAV_PUSH_VIEW_CENTERX_OFFSET, _pushView.center.y);
        _pushView.alpha = 1.0;
    }else{
        _pushView = nil;
    }
    return _pushView;
}

//pop或者取消pop操作
- (void)closeLeftView:(BOOL)isClose{
    [self registPanGesture:NO];
    _willOpen = NO;
    UIView * mainView = self.view;
    __weak  typeof(self) sf = self;
    if(isClose){
        [UIView animateWithDuration:KWHC_NAV_ANIMATION_DURING delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            _popView.center = CGPointMake(KWHC_NAV_POP_VIEW_CENTERX_OFFSET, _popView.center.y);
            _popView.alpha = KWHC_NAV_POP_VIEW_ALPHA;
            mainView.transform = [sf initAffineTransform:0.0];
        } completion:^(BOOL finished) {
            [sf registPanGesture:YES];
            [_popView  removeFromSuperview];
            _popView = nil;
        }];
    }else{//pop opeartion
        [UIView animateWithDuration:KWHC_NAV_ANIMATION_DURING delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            mainView.transform = [sf initAffineTransform:CGRectGetWidth(mainView.frame)];
            _popView.center = CGPointMake(CGRectGetWidth(_popView.frame) / 2.0, _popView.center.y);
            _popView.alpha = 1.0;
        } completion:^(BOOL finished) {
            [sf registPanGesture:YES];
            _isTouchPop = YES;
            mainView.transform = [sf initAffineTransform:0];
            [sf popViewControllerAnimated:NO];
        }];
    }
}

#pragma mark - viewLoad
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//重载父类push方法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if(_snapshootList == nil){
        _snapshootList = [NSMutableArray array];
    }
    [_snapshootList addObject:[[UIImageView alloc]initWithImage:[self snapshootNavBar:viewController]]];
    [self pushView];
    //忽略第一次push操作
    if(_pushView && animated && _snapshootList != nil){

        __weak  typeof(self) sf = self;
        //防止重复push
        _topView = self.topViewController.view;
        _topView.userInteractionEnabled = NO;
        [super pushViewController:viewController animated:NO];
        self.view.transform = [self initAffineTransform:CGRectGetWidth(self.view.frame)];
        UIView * oldPushView = [self.view.superview viewWithTag:KWHC_NAV_LEFT_PUSH_VIEW_TAG];
        if(oldPushView){
            [oldPushView removeFromSuperview];
            oldPushView = nil;
        }
        _pushView.center = CGPointMake(CGRectGetWidth(_pushView.frame) / 2.0, _pushView.center.y);
        [self.view.superview insertSubview:_pushView belowSubview:self.view];
        [UIView animateWithDuration:KWHC_NAV_ANIMATION_DURING delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            _pushView.center = CGPointMake(-CGRectGetWidth(_pushView.frame) / 2.0, _pushView.center.y);
            _pushView.alpha = KWHC_NAV_POP_VIEW_ALPHA;
            sf.view.transform = [sf initAffineTransform:0];
        } completion:^(BOOL finished) {
            [_pushView removeFromSuperview];
            _pushView = nil;
        }];

    }else{

        [super pushViewController:viewController animated:animated];
    }
}

//重写父类pop方法
- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
    UIViewController  * viewController = nil;
    if(!_isTouchPop){
        //不是触摸弹出操作
        __weak  typeof(self) sf = self;
        __block UIView  * popView = [[UIImageView alloc]initWithImage:[self snapshootNavBar:nil]];
        viewController = [super popViewControllerAnimated:NO];
        if(popView){
            self.view.transform = [self initAffineTransform:-CGRectGetWidth(self.view.frame)];
            self.view.alpha = KWHC_NAV_POP_VIEW_ALPHA;
            UIView  * oldPopView = [self.view.superview viewWithTag:KWHC_NAV_LEFT_VIEW_TAG];
            if(oldPopView){
                [oldPopView removeFromSuperview];
                oldPopView = nil;
            }
            popView.center = CGPointMake(CGRectGetWidth(popView.frame) / 2.0, popView.center.y);
            [self.view.superview insertSubview:popView belowSubview:self.view];
            [UIView animateWithDuration:KWHC_NAV_ANIMATION_DURING delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                popView.center = CGPointMake(CGRectGetWidth(popView.frame) * 1.5, popView.center.y);
                sf.view.transform = [sf initAffineTransform:0];
                sf.view.alpha = 1.0;
            } completion:^(BOOL finished) {
                [popView removeFromSuperview];
                popView = nil;
                [_snapshootList removeLastObject];
            }];
        }
    }else{
        //清除popview的快照存储
        [_snapshootList removeLastObject];
        [_popView removeFromSuperview];
        _popView = nil;
        viewController = [super popViewControllerAnimated:animated];
    }
    _isTouchPop = NO;
    return viewController;
}

#pragma mark - UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    }
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    if(_topView != nil){
        _topView.userInteractionEnabled = YES;
    }
}

@end

时间: 2024-10-31 07:43:51

iOS开发系列之常用框架开发集—自定义UINavitationController开发1的相关文章

关于jsp商城开发中一些常用框架的介绍

Struts跟Tomcat.Turbine等诸多Apache项目一样,是开源软件,这是它的一大优点,使java商城产品以及jsp商城开发者能更深入的了解其内部实现机制.除此之外,在 java商城开发 中Struts的优点主要集中体现在两个方面:Taglib和页面导航.Taglib是Struts的标记库,比较灵活,能大大提高开发效率.另外,就目前国内的JSP开发者而言,除了使用JSP自带的常用标记外,很少开发自己的标记,或许Struts是一个很好的起点.struts历经6年多的发展,是目前用户数最

ios系统架构及常用框架

1.iOS基于UNIX系统,因此从系统的稳定性上来说它要比其他操作系统的产品好很多 2.iOS的系统架构分为四层,由上到下一次为:可触摸层(Cocoa Touch layer).媒体层(Media layer).核心服务层(Core Services layer).核心操作系统层(Core OS layer)如图: (1) 触摸层:为应用程序开发提供了各种常用的框架并且大部分框架与界面有关,本质上来说它负责用户在iOS设备上的触摸交互操作.它包括以下这些组件: Multi-Touch Event

[052] 微信公众平台开发视频公开课第2讲-自定义菜单开发讲解

微信公众平台开发视频公开课第2讲将为大家讲解自定义菜单的相关知识,时间是2014年5月24日20:00-22:00.本次课程的大纲如下: 1.自定义菜单简介 1)如何获得菜单权限 2)菜单按钮分类(click和view) 2.编辑模式下的菜单使用 1)创建菜单 2)预览发布 3)注意事项 3.开发模式下的菜单使用 1)菜单接口介绍 2)如何发起https请求(两种方法,IBM JDK环境) 3)获取access_token 4)如何封装菜单结构 5)创建菜单 6)处理菜单点击事件 7)菜单的查询

iOS第三方Api及常用框架总结

iOS常用框架汇总: SVProgressHUD:产生覆盖层,禁止某种操作 SDWebImage: 专业下载图片框架 AFN:网络数据请求框架 MJExtension,模型对象之间互转 facebook/pop:各种动画的实现 第三方库 :推送:继承激光推送 定位:百度地图集成 支付:支付宝 人脸识别:http://www.faceplusplus.com.cn/ 短信验证:http://sms.mob.com/#/sms 数据存储:https://leancloud.cn/?

iOS开发系列之常用自定义控件开发集—自定义单选按钮或者多选按钮控件开发

在我们实际开发中我们做登陆或者注册功能时往往需要勾选某个协议这个时候就需要用到CheckBox按钮,CheckBox是pc或者android上得控件ios没有,所以需要我们自定义. WHC_RadioButton.h头文件如下: // // WHC_RadioButton.h // CTBMobileBank // // Created by 吴海超 on 15/4/1. // // #import <UIKit/UIKit.h> #define KWHC_IMAGE_SIZE (15.0)

iOS开发系列之常用自定义控件开发集—自定义状态栏消息提示控件开发

在实际开发中消息提示时很常见的需求,为了个性化和拥有简洁的UI状态栏提示是比较好的方案,好处很多如:不遮挡主UI,新意,下面贴出实现代码. WHC_StatusBarMessage.h头文件如下: // // WHCStatusBarMessage.m // WHCStatusBarMessage // // Created by apple on 14-3-28. // Copyright (c) 2014年 apple. All rights reserved. // #import "WH

iOS开发系列之常用自定义控件开发集—自定义多选按钮控件开发

在实际开发中很多时候我们需要用到下拉列表,我们下面来实现一下. WHC_ComboBox.h头文件如下: // // WHC_ComboBox.h // WHC_ComboBox // // Created by 吴海超 on 15/4/2. // // #import <UIKit/UIKit.h> @interface WHC_ComboBox : UIButton @end WHC_ComboBox.m源文件如下: // // WHC_ComboBox.m // WHC_ComboBox

iOS开发系列之常用自定义控件开发集—自定义UITableViewCell侧滑菜单控件开发

在很多app中就有UITableViewCell左滑出现菜单如系统删除按钮,但是系统的只能有一个,有很多需求需要个性化不仅可以放文字还可以放按钮修改背景色创建多个菜单项,那么系统提供的肯定不适合,所以我们需要自己手工打造. 直接上代码如下: WHC_MenuCell.h 头文件如下: // // WHC_MenuCell.m // WHC_MenuCell // // Created by 吴海超 on 15/4/3. // Copyright (c) 2015年 Sinosun Technol

Android开发系列之常用正则语法

正则表达式的语法太过复杂,先总结常用语法为十四则,如下: 1.   \b  元字符,匹配单词的开始与结束   2.    . 元字符,匹配除换行符以外的任意字符   3.    * 元字符,匹配*之前内容,连续重复使用任意次   4.    \d 元字符,匹配任意数字   5.    \s 元字符,匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等   6.    \w 元字符,匹配字母或数字或下划线或汉字等   7.    ^和& 元字符,匹配位置,匹配字符串的开始与结束