关于tabbarViewController的左右滑动切换

在我们开发的过程中,有时会有左右侧滑tabbarViewController切换控制器的需求,在我自己做项目的时候遇到了此类需求,现在就在此记录一下我当时的做法,废话不多说,直接上代码:

在iOS7.0以前,要实现这样的效果,只有自定义TabBar了,但这很麻烦。而在iOS7.0以后,苹果在UITabBarControllerDelegate中增加了下面两个代理方法:

- (nullable id <UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController  interactionControllerForAnimationController: (id<UIViewControllerAnimatedTransitioning>)animationController;

- (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController  animationControllerForTransitionFromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC;

自定义的滑动代理,在此实现tabbarViewController的两个新添加的滑动的代理方法

//  ScrollTabBarDelegate.h

 

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

 

@interface ScrollTabBarDelegate : NSObject <UITabBarControllerDelegate>

 

@property (nonatomic, assign) BOOL interactive;

@property (nonatomic, strong) UIPercentDrivenInteractiveTransition *interactionController;

 

@end

//

//  ScrollTabBarDelegate.m

#import "ScrollTabBarDelegate.h"

#import "ScrollTabBarAnimator.h"

 

@interface ScrollTabBarDelegate ()

 

@property (nonatomic, strong) ScrollTabBarAnimator *tabBarAnimator;

 

@end

 

@implementation ScrollTabBarDelegate

 

- (instancetype)init {

    if (self = [super init]) {

        _interactive = NO;

        _interactionController = [[UIPercentDrivenInteractiveTransition alloc] init];

        _tabBarAnimator = [[ScrollTabBarAnimator alloc] init];

 

    }

    return self;

}

 

- (nullable id <UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController

                               interactionControllerForAnimationController: (id <UIViewControllerAnimatedTransitioning>)animationController {

    return self.interactive ? self.interactionController : nil;

}

 

- (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController

                     animationControllerForTransitionFromViewController:(UIViewController *)fromVC

                                                       toViewController:(UIViewController *)toVC {

    

    NSInteger fromIndex = [tabBarController.viewControllers indexOfObject:fromVC];

    NSInteger toIndex = [tabBarController.viewControllers indexOfObject:toVC];

    self.tabBarAnimator.tabScrollDirection = (toIndex < fromIndex) ? TabLeftDirection: TabRightDirection;

    return self.tabBarAnimator;

 

}

 

@end

在自定义一个动画的类,实现滑动切换tabbar时加载动画效果:

//  ScrollTabBarAnimator.h

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

 

typedef NS_ENUM(NSInteger,TabOperationDirection) {

    TabLeftDirection,

    TabRightDirection

};

 

@interface ScrollTabBarAnimator : NSObject <UIViewControllerAnimatedTransitioning>

 

@property (nonatomic, assign) TabOperationDirection tabScrollDirection;

 

@end

//  ScrollTabBarAnimator.m

#import "ScrollTabBarAnimator.h"

 

@implementation ScrollTabBarAnimator

 

//动画持续时间

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {

    return 0.3;

}

 

//动画执行效果

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {

    

    // 获取 toView fromView

    UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

    UIView *containerView = [transitionContext containerView];

    if (!toViewController || !fromViewController || !containerView) return;

    

    // 给 toView fromView 设定相应的值

    toViewController.view.transform = CGAffineTransformIdentity;

    fromViewController.view.transform = CGAffineTransformIdentity;

    CGFloat translation = containerView.frame.size.width;

 

    switch (self.tabScrollDirection) {

        case TabLeftDirection:

            translation = translation;

            break;

        case TabRightDirection:

            translation = -translation;

            break;

        default:

            break;

    }

 

    [containerView addSubview:toViewController.view];

    toViewController.view.transform = CGAffineTransformMakeTranslation(-translation, 0);

    // 真正的变化

    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{

        fromViewController.view.transform = CGAffineTransformMakeTranslation(translation, 0);

        toViewController.view.transform = CGAffineTransformIdentity;

    } completion:^(BOOL finished) {

        fromViewController.view.transform = CGAffineTransformIdentity;

        toViewController.view.transform = CGAffineTransformIdentity;

        [transitionContext completeTransition:![transitionContext transitionWasCancelled]];

    }];

}

 

@end

在 TabBarController.m 中 实现的方法

导入 ScrollTabBarDelegate 的头文件后,声明两个对象

@property (nonatomic, assign) NSInteger subViewControllerCount;

@property (nonatomic, strong) ScrollTabBarDelegate *tabBarDelegate;

- (void)viewDidLoad {

    [super viewDidLoad];

    #pragma mark   tabbar滑动切换手势

    // 正确的给予 count

    self.subViewControllerCount = self.viewControllers ? self.viewControllers.count : 0;

设置 tabbarViewController 的代理为 ScrollTabBarDelegate ,并给 tabbarViewController 的view添加滑动手势

    // 代理

    self.tabBarDelegate = [[ScrollTabBarDelegate alloc] init];

    self.delegate = self.tabBarDelegate;

    // 增加滑动手势

    self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panHandle:)];

    [self.view addGestureRecognizer:self.panGesture];

    

}

 实现滑动手势,切换tabbarViewController的item到不同的控制器

- (void)panHandle:(UIPanGestureRecognizer *)panGesture {

    // 获取滑动点

    CGFloat translationX = [panGesture translationInView:self.view].x;

    CGFloat progress = fabs(translationX)/self.view.frame.size.width;

    

    switch (panGesture.state) {

        case UIGestureRecognizerStateBegan:

        {

            self.tabBarDelegate.interactive = YES;

            CGFloat velocityX = [panGesture velocityInView:self.view].x;

            if (velocityX < 0) {

                if (self.selectedIndex < self.subViewControllerCount - 1) {

                    self.selectedIndex += 1;

                }

            }

            else {

                if (self.selectedIndex > 0) {

                    self.selectedIndex -= 1;

                }

            }

        }

            break;

        case UIGestureRecognizerStateChanged:

        {

            [self.tabBarDelegate.interactionController updateInteractiveTransition:progress];

        }

            

            break;

        case UIGestureRecognizerStateEnded:

        case UIGestureRecognizerStateFailed:

        case UIGestureRecognizerStateCancelled:

        {

            if (progress > 0.3) {

                self.tabBarDelegate.interactionController.completionSpeed = 0.99;

                [self.tabBarDelegate.interactionController finishInteractiveTransition];

            }else{

                //转场取消后,UITabBarController 自动恢复了 selectedIndex 的值,不需要我们手动恢复。

                self.tabBarDelegate.interactionController.completionSpeed = 0.99;

                [self.tabBarDelegate.interactionController cancelInteractiveTransition];

            }

            self.tabBarDelegate.interactive = NO;

        }

            break;

        default:

            break;

    }

}

这样实现以后,会出现一个问题,就是当跳转到子控制器的时候,子控制器也可以滑动,这就不对了,于是果断的开始查找原因,发现所有的控制器的 

rootViewController 都是 tabbarViewController,所以需要在跳转的时候吧 tabbarViewController 的view的滑动手势给移除掉,当返回来的时候再给加上去,于是把 UIPanGestureRecognizer 的对象在tabbarViewController.h 中搞成一个全局对象 

@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;

在自定义的 UINavigationController 中,重写 pushViewController 方法,在此方法中移除tabbarViewController 的view的滑动手势,代码如下: 

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {

    

    if (self.viewControllers.count > 0) {

        viewController.hidesBottomBarWhenPushed = YES;

        // 跳转后移除滑动手势

        [[UIApplication sharedApplication].delegate.window.rootViewController.view removeGestureRecognizer:viewController.cyl_tabBarController.panGesture];

   注册一个通知,通知在第一层的控制器吧tabbarViewController 的view的滑动手势给添加上去

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollNextViewController) name:@"SCROLLTABBARCONTROLLER" object:nil];

 

    }

        [super pushViewController:viewController animated:animated];

}

当返回到第一层的控制器的时候,在返回按钮点击的时候发布一个通知,通知在第一层的控制器吧tabbarViewController 的view的滑动手势给添加上去

-(void)scrollNextViewController {

    

    if (self.childViewControllers.count == 1 && [(AppDelegate *)[UIApplication sharedApplication].delegate isBackBtn] == YES) {

        // 返回后重新添加滑动手势

        [[UIApplication sharedApplication].delegate.window.rootViewController.view addGestureRecognizer:[UIApplication sharedApplication].delegate.window.rootViewController.cyl_tabBarController.panGesture];

    }

}

结束后别忘了移除通知

- (void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

到此处,关于tabbarViewController的左右滑动切换的问题算是解决了。

转载于:https://www.cnblogs.com/zhufengshibei/p/7358159.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以在tabbarviewcontroller的viewDidLoad方法中添加以下代码来实现: ``` // 创建5个视图控制器 let xVC = XViewController() let yVC = YViewController() let zVC = ZViewController() let mVC = MViewController() let nVC = NViewController() // 创建5个导航控制器,并将对应的视图控制器设置为根视图控制器 let xNav = UINavigationController(rootViewController: xVC) let yNav = UINavigationController(rootViewController: yVC) let zNav = UINavigationController(rootViewController: zVC) let mNav = UINavigationController(rootViewController: mVC) let nNav = UINavigationController(rootViewController: nVC) // 设置未选中图片与选中图片 xNav.tabBarItem = UITabBarItem(title: "X", image: UIImage(named: "unselectedImage"), selectedImage: UIImage(named: "selectedImage")) yNav.tabBarItem = UITabBarItem(title: "Y", image: UIImage(named: "unselectedImage"), selectedImage: UIImage(named: "selectedImage")) zNav.tabBarItem = UITabBarItem(title: "Z", image: UIImage(named: "unselectedImage"), selectedImage: UIImage(named: "selectedImage")) mNav.tabBarItem = UITabBarItem(title: "M", image: UIImage(named: "unselectedImage"), selectedImage: UIImage(named: "selectedImage")) nNav.tabBarItem = UITabBarItem(title: "N", image: UIImage(named: "unselectedImage"), selectedImage: UIImage(named: "selectedImage")) // 设置未选中时与选中时的tab文字颜色更换 UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.gray], for: .normal) UITabBarItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.blue], for: .selected) // 将5个导航控制器添加到tabbarviewcontroller中 self.viewControllers = [xNav, yNav, zNav, mNav, nNav] ``` 这样就可以实现在tabbarviewcontroller文件里添加一个uinavigantioncontroller,点击不同的item时,实现未选中图片与选中图片的切换、未选中时与选中时的tab文字颜色更换,且能跳转到不同的viewcontroller文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值