控制器切换(网易新闻效果)

有的时候设计开发的app用了UITabBarController控制器后,跳转到相应的导航栏控制器,而导航栏的控制器又有子控制,再子控制器中实现控制器的切换一般都不再采用UITabBarController实现,而是自己设计相应的控制器切换按钮实现,类似于网易新闻那样的效果.
如网易新闻下边的导航条
最终实现的效果如下,点击按钮 切换 控制器:
效果图
具体实现原理:
在AppDelegate的函数中设置主窗口:

-  (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   //初始化窗口
    self.window = [[UIWindow alloc] init];
    self.window.frame = [UIScreen mainScreen].bounds;
    //设置主控制器
    XCMainController *mainVc = [[XCMainController alloc] init];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:mainVc];
    self.window.rootViewController = nav;
    //显示
    [self.window makeKeyAndVisible];
    return YES;
}
思想:创建一个主控制,然后用主控制来管理各个子控制,同时自定义一个导航按钮切换View,在其中添加各个按钮,并实现代理方法,当点击了按钮后,可以在主控制实现其代理方法,然后就可以完成相应的控制器切换.
初始化主控制器:
#import "XCNavBar.h"
- (void)viewDidLoad{
    [super viewDidLoad];
    //设置导航栏题目
    self.navigationItem.title = @"主控制器";
    //添加导航条
    XCNavBar *navBar = [[XCNavBar alloc] init];
    navBar.backgroundColor = [UIColor whiteColor];
    navBar.delegate = self;
    navBar.frame = CGRectMake(0, navigationH, viewW, navBarH);
    [self.view addSubview:navBar];
 }

自定义导航按钮:

.h文件
typedef enum{//按钮类型
    XCNavBarButtonTypeOne = 0,
    XCNavBarButtonTypeTwo,
    XCNavBarButtonTypeThree,
    XCNavBarButtonTypeFour
} XCNavBarButtonType;
//代理实现
@class XCNavBar;
@protocol XCNavBarDelegate <NSObject>
@optional//可选的
- (void)navBar:(XCNavBar *)navBar didSelectedButton:(XCNavBarButtonType)buttonType;
@end
//属性方法
@property (nonatomic, weak) id<XCNavBarDelegate> delegate;

.m文件
//属性
@property (nonatomic, strong) UIButton *selectedBtn;
//具体方法
- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
    //添加按钮
        [self addButtonWithTitle:@"one" buttonType:XCNavBarButtonTypeOne];
        [self addButtonWithTitle:@"two" buttonType:XCNavBarButtonTypeTwo];
        [self addButtonWithTitle:@"three" buttonType:XCNavBarButtonTypeThree];
        [self addButtonWithTitle:@"four" buttonType:XCNavBarButtonTypeFour];
    }
    return self;
}

//添加一个按钮
- (void)addButtonWithTitle:(NSString *)title buttonType:(XCNavBarButtonType)type{
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    [btn setTitle:title forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal];

    [btn setTitleColor:[UIColor darkGrayColor] forState:UIControlStateDisabled];

    btn.tag = type;
    [self addSubview:btn];
    [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
    if (type == XCNavBarButtonTypeOne){
        [self btnClick:btn];
    }
}
//监听按钮点击
- (void)btnClick:(UIButton *)btn{
    self.selectedBtn.enabled = YES;
    btn.enabled = NO;
    self.selectedBtn = btn;
    //实现代理方法
    if ([self.delegate respondsToSelector:@selector(navBar:didSelectedButton:)]) {
        [self.delegate navBar:self didSelectedButton:btn.tag];
    }    
}
//计算子控件的位置
- (void)layoutSubviews{
    [super layoutSubviews];
    NSInteger count = self.subviews.count;
    CGFloat btnW = self.bounds.size.width / count;
    CGFloat btnH = self.bounds.size.height;
    CGFloat btnX = 0;
    CGFloat btnY = 0;
    for (int i = 0; i < count; i++) {
        UIButton *btn = self.subviews[i];
        btnX = i * btnW;
        btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
    }
}

主控制器中添加自控制器,并实现控制器的相应切换

/** 屏幕宽度 */
#define viewW self.view.frame.size.width
/** 屏幕高度 */
#define viewH self.view.frame.size.height
/** 子控制器高度 */
#define subViewH (viewH - navigationH - navBarH)
/** 导航条高度 */
#define navigationH 64
/** 导航按钮高度 */
#define navBarH 44
/** 子控制器Y值 */
#define subViewY (navigationH + navBarH)
//属性
//强引用,否则会被释放
@property (nonatomic, strong) XCOneController *oneVc;
@property (nonatomic, strong) XCTwoViewController *twoVc;
@property (nonatomic, strong) XCThreeController *threeVc;
@property (nonatomic, strong) XCFourController *fourVc;
/** 当前控制器 */
@property (nonatomic, strong) UIViewController *currentView;
//具体方法
- (void)viewDidLoad{
    [super viewDidLoad];
   //添加自控制器
    self.oneVc = [[XCOneController alloc] init];
    self.oneVc.view.frame = CGRectMake(0, subViewY, viewW, subViewH);
    [self addChildViewController:self.oneVc];

    self.twoVc = [[XCTwoViewController alloc] init];
    self.twoVc.view.frame = CGRectMake(0, subViewY, viewW, subViewH);
    [self addChildViewController:self.twoVc];

    self.threeVc = [[XCThreeController alloc] init];
    self.threeVc.view.frame = CGRectMake(0, subViewY, viewW, subViewH);
    [self addChildViewController:self.threeVc];

    self.fourVc = [[XCFourController alloc] init];
    self.fourVc.view.frame = CGRectMake(0, subViewY, viewW, subViewH);
    [self addChildViewController:self.fourVc];

    //设置默认控制器
    self.currentView = self.oneVc;
    [self.view addSubview:self.oneVc.view];
}
/**
 *  控制器切换方法实现
 */
- (void)replaceOldViewController:(UIViewController *)oldVc toNewViewController:(UIViewController *)newVc{
    //要切换的控制器为当前控制器,则直接返回
    if (self.currentView == newVc) return;
    /**
     *  transitionFromViewController:toViewController:duration:options:animations:completion:
     *  fromViewController    当前显示在父视图控制器中的子视图控制器
     *  toViewController        将要显示的姿势图控制器
     *  duration                动画时间(这个属性,old friend 了 O(∩_∩)O)
     *  options              动画效果(渐变,从下往上等等,具体查看API)UIViewAnimationOptionTransitionCrossDissolve
     *  animations            转换过程中得动画
     *  completion            转换完成
     */
    [self addChildViewController:newVc];
    [self transitionFromViewController:oldVc toViewController:newVc duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:nil completion:^(BOOL finished) {
        if (finished) {
            [newVc didMoveToParentViewController:self];
            [oldVc willMoveToParentViewController:nil];
            [oldVc removeFromParentViewController];
            self.currentView = newVc;
        }else{
            self.currentView = oldVc;
        }
    }];
}

最后在主控制器中导航按钮的实现代理方法,完成控制器的切换

#pragma mark - XCNavBarDelegate代理方法
- (void)navBar:(XCNavBar *)navBar didSelectedButton:(XCNavBarButtonType)buttonType{
    switch (buttonType) {
        case XCNavBarButtonTypeOne:
            [self replaceOldViewController:self.currentView toNewViewController:self.oneVc];
            break;
        case XCNavBarButtonTypeTwo:
            [self replaceOldViewController:self.currentView toNewViewController:self.twoVc];
            break;
        case XCNavBarButtonTypeThree:
            [self replaceOldViewController:self.currentView toNewViewController:self.threeVc];
            break;
        case XCNavBarButtonTypeFour:
            [self replaceOldViewController:self.currentView toNewViewController:self.fourVc];
            break;
        default:
            break;
    }
}

最后:源代码地址
github源码地址

posted @ 2016-03-12 11:39  zsper  阅读(135)  评论(0编辑  收藏  举报