You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Objective-C中实现MDTabBar滑动切换标签及仿Android视图控制器

Got it, let's walk through how to build swipe-to-switch tabs with MDTabBar in Objective-C, plus that Android-style view controller transition effect you want. I know CarbonKit works really well, but we can replicate that functionality directly on top of Material Components' MDTabBar with these steps:

1. Setup MDTabBar & UIPageViewController

First, we'll pair MDTabBar with a UIPageViewController—this is the core setup for swipeable tab content. Here's how to initialize both components:

Header File (ViewController.h)

#import <UIKit/UIKit.h>
#import <MaterialComponents/MaterialTabs.h>

@interface ViewController : UIViewController <MDCTabBarDelegate, UIPageViewControllerDataSource, UIPageViewControllerDelegate>

@property (nonatomic, strong) MDCTabBar *tabBar;
@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *contentViewControllers;

@end

Implementation File (ViewController.m)

Start by initializing your tab items, content view controllers, and adding both components to your main view:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1. Create your content view controllers
    self.contentViewControllers = @[
        [[UIViewController alloc] init],
        [[UIViewController alloc] init],
        [[UIViewController alloc] init]
    ];
    // Add distinct background colors to test transitions
    ((UIViewController *)self.contentViewControllers[0]).view.backgroundColor = [UIColor systemRedColor];
    ((UIViewController *)self.contentViewControllers[1]).view.backgroundColor = [UIColor systemGreenColor];
    ((UIViewController *)self.contentViewControllers[2]).view.backgroundColor = [UIColor systemBlueColor];
    
    // 2. Initialize MDTabBar
    self.tabBar = [[MDCTabBar alloc] initWithFrame:CGRectMake(0, self.view.safeAreaInsets.top, self.view.bounds.size.width, 48)];
    self.tabBar.items = @[
        [[UITabBarItem alloc] initWithTitle:@"Tab 1" image:nil tag:0],
        [[UITabBarItem alloc] initWithTitle:@"Tab 2" image:nil tag:1],
        [[UITabBarItem alloc] initWithTitle:@"Tab 3" image:nil tag:2]
    ];
    self.tabBar.delegate = self;
    self.tabBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
    [self.view addSubview:self.tabBar];
    
    // 3. Initialize UIPageViewController
    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll 
                                                         navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal 
                                                                       options:nil];
    self.pageViewController.dataSource = self;
    self.pageViewController.delegate = self;
    // Set initial view controller
    [self.pageViewController setViewControllers:@[self.contentViewControllers[0]] 
                                      direction:UIPageViewControllerNavigationDirectionForward 
                                       animated:NO 
                                     completion:nil];
    
    // Add page view controller to main view
    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
    self.pageViewController.view.frame = CGRectMake(0, 
                                                    CGRectGetMaxY(self.tabBar.frame), 
                                                    self.view.bounds.size.width, 
                                                    self.view.bounds.size.height - CGRectGetMaxY(self.tabBar.frame) - self.view.safeAreaInsets.bottom);
    self.pageViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.pageViewController didMoveToParentViewController:self];
}

We need to make sure tapping a tab swipes the page view, and swiping the page updates the tab selection.

Handle Tab Bar Tap Events

Implement the MDCTabBarDelegate method to trigger page transitions:

- (void)tabBar:(MDCTabBar *)tabBar didSelectItemAtIndex:(NSUInteger)index {
    UIPageViewControllerNavigationDirection direction = index > tabBar.selectedItemIndex ? 
        UIPageViewControllerNavigationDirectionForward : 
        UIPageViewControllerNavigationDirectionReverse;
    
    [self.pageViewController setViewControllers:@[self.contentViewControllers[index]] 
                                      direction:direction 
                                       animated:YES 
                                     completion:nil];
}

Handle Page Swipe Events

Update the tab bar when the user swipes between pages using UIPageViewControllerDelegate:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
    NSUInteger index = [self.contentViewControllers indexOfObject:viewController];
    return (index > 0) ? self.contentViewControllers[index - 1] : nil;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
    NSUInteger index = [self.contentViewControllers indexOfObject:viewController];
    return (index < self.contentViewControllers.count - 1) ? self.contentViewControllers[index + 1] : nil;
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed {
    if (completed) {
        UIViewController *currentVC = pageViewController.viewControllers.firstObject;
        NSUInteger currentIndex = [self.contentViewControllers indexOfObject:currentVC];
        [self.tabBar setSelectedItemIndex:currentIndex animated:YES];
    }
}

3. Add Android-Style Transition Animation

The default scroll transition is close, but to match Android's smoother slide effect, we'll create a custom animator:

Custom Transition Animator

Add this helper class to your project:

@interface SlideTransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign) UIPageViewControllerNavigationDirection direction;
@end

@implementation SlideTransitionAnimator

- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
    return 0.35; // Match Android's typical transition speed
}

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *container = transitionContext.containerView;
    
    // Set initial frames
    CGRect containerBounds = container.bounds;
    toVC.view.frame = CGRectOffset(containerBounds, 
                                   self.direction == UIPageViewControllerNavigationDirectionForward ? containerBounds.size.width : -containerBounds.size.width, 
                                   0);
    [container addSubview:toVC.view];
    
    // Animate transition
    [UIView animateWithDuration:[self transitionDuration:transitionContext]
                          delay:0
         usingSpringWithDamping:0.9
          initialSpringVelocity:0.8
                        options:UIViewAnimationOptionCurveEaseInOut
                     animations:^{
                         fromVC.view.frame = CGRectOffset(containerBounds, 
                                                          self.direction == UIPageViewControllerNavigationDirectionForward ? -containerBounds.size.width : containerBounds.size.width, 
                                                          0);
                         toVC.view.frame = containerBounds;
                     } completion:^(BOOL finished) {
                         [fromVC.view removeFromSuperview];
                         [transitionContext completeTransition:finished];
                     }];
}

@end

Attach Animator to Page View Controller

Update your viewDidLoad to set the transition delegate, then implement the delegate method to return your custom animator:

// Add this line in viewDidLoad after initializing pageViewController
self.pageViewController.transitionDelegate = self;

// Implement UIPageViewControllerTransitionDelegate
- (id<UIViewControllerAnimatedTransitioning>)pageViewController:(UIPageViewController *)pageViewController animationControllerForTransitionFromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
    SlideTransitionAnimator *animator = [[SlideTransitionAnimator alloc] init];
    NSUInteger fromIndex = [self.contentViewControllers indexOfObject:fromVC];
    NSUInteger toIndex = [self.contentViewControllers indexOfObject:toVC];
    animator.direction = toIndex > fromIndex ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse;
    return animator;
}

4. Polish the Tab Bar Style

Make the tab bar match Material Design guidelines (optional but recommended):

// Add these lines after initializing self.tabBar
self.tabBar.selectedItemTintColor = [UIColor systemBlueColor];
self.tabBar.unselectedItemTintColor = [UIColor systemGrayColor];
self.tabBar.indicatorColor = [UIColor systemBlueColor];
self.tabBar.indicatorHeight = 2;
self.tabBar.scrollable = YES; // Enable scrolling if you have more than 3 tabs

That's it! This setup will give you swipe-to-switch tabs with MDTabBar, plus a smooth Android-style transition between view controllers—no CarbonKit required.

内容的提问来源于stack exchange,提问作者Vivek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:03:21