1. 程式人生 > >漫談TabBar(一)

漫談TabBar(一)

UITabbar是ios框架中重要的元件,通常我們一個app只會建立一個tabbar來管理整個app的流程

手動建立一個tabbarcontroller:

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

    timerViewController *timer = [[timerViewController alloc] initWithNibName:@"timerViewController" bundle:nil];
    appleViewController *apple0 = [[appleViewController alloc] initWithNibName:@"appleViewController"
bundle:nil]; appleViewController *apple1 = [[appleViewController alloc] initWithNibName:@"appleViewController" bundle:nil]; appleViewController *apple2 = [[appleViewController alloc] initWithNibName:@"appleViewController" bundle:nil]; appleViewController *apple3 = [[appleViewController alloc] initWithNibName:@"appleViewController"
bundle:nil]; appleViewController *apple4 = [[appleViewController alloc] initWithNibName:@"appleViewController" bundle:nil]; barViewController *bar = [[barViewController alloc] init]; [bar setViewControllers:[NSArray arrayWithObjects:timer,apple0,apple1,apple2,apple3,apple4, nil]]; [self
.window setRootViewController:bar]; [self.window makeKeyAndVisible]; return YES;

ios原生TabBar效果

如果管理的controller超過5個,會自動的變成more的標籤。點選more會彈出一個由tabbar管理的tableView,在這不做過多的描述,手冊上很清楚。

然後,我們覺得這個原生的TabBar太low了,我們想改一下造型,比如高度,顏色?然後

    bar.tabBar.backgroundColor = [UIColor blueColor];
    CGRect ct = bar.tabBar.frame;
    ct.size.height = ct.size.height * 2;
    [bar.tabBar setFrame:ct];

這裡寫圖片描述

嗯,高度沒有變化,顏色變了?好像沒有變成我們設定的顏色,不過還挺好看的 。檢視手冊tabbar的預設高度為49 ,我們自己建立一個tablebarController來探究下, 在viewDidLayoutSubviews中將整個view的層級結構打印出來。。

#import "barViewController.h"
#import "customTabBar.h"

@interface barViewController ()

@end

@implementation barViewController

- (void)viewDidLoad {
    [super viewDidLoad];  
}

-(void)viewDidLayoutSubviews{
    [self printViewHierarchy:self.view];
}

//view樹
- (void)printViewHierarchy:(UIView *)superView
{
    static uint level = 0;
    for(uint i = 0; i < level; i++){
        printf("\t");
    }

    const char *className = NSStringFromClass([superView class]).UTF8String;
    const char *frame = NSStringFromCGRect(superView.frame).UTF8String;
    printf("%s:%s\n", className, frame);

    ++level;
    for(UIView *view in superView.subviews){
        [self printViewHierarchy:view];
    }
    --level;
}

結果

UILayoutContainerView:{{0, 0}, {375, 667}}
    UITransitionView:{{0, 0}, {375, 667}}
        UIViewControllerWrapperView:{{0, 0}, {375, 667}}
            UIView:{{0, 0}, {375, 667}}
                UILabel:{{135, 137}, {165, 21}}
    UITabBar:{{0, 618}, {375, 49}}
        _UITabBarBackgroundView:{{0, 0}, {375, 49}}
            _UIBackdropView:{{0, 0}, {375, 49}}
                _UIBackdropEffectView:{{0, 0}, {375, 49}}
                UIView:{{0, 0}, {375, 49}}
        UITabBarButton:{{2, 1}, {71, 48}}
            UITabBarButtonLabel:{{24, 35}, {23, 12}}
        UITabBarButton:{{77, 1}, {71, 48}}
            UITabBarButtonLabel:{{21.5, 35}, {27.5, 12}}
        UITabBarButton:{{152, 1}, {71, 48}}
            UITabBarButtonLabel:{{21.5, 35}, {27.5, 12}}
        UITabBarButton:{{227, 1}, {71, 48}}
            UITabBarButtonLabel:{{21.5, 35}, {27.5, 12}}
        UITabBarButton:{{302, 1}, {71, 48}}
            UITabBarSwappableImageView:{{23.5, 15.5}, {24, 5}}
            UITabBarButtonLabel:{{23.5, 35}, {24, 12}}
        UIImageView:{{0, -0.5}, {375, 0.5}}

UILayoutContainerView,UITransitionView,UIViewControllerWrapperView,UITabBarBackgroundView,UIBackdropView,UIBackdropEffectView在手冊中都找不到,apple並沒有公開這些view的資訊,我們自己hack下。

UILayoutContainerView :不用說肯定是整個控制器的最頂層view..
UITransitionView:我們改改他的高度看看效果,在viewDidLayoutSubviews中加入程式碼

    for(UIView *view in self.view.subviews){ 
        if ([view isKindOfClass:NSClassFromString(@"UITransitionView")]) {
            CGRect rect = view.frame;
            rect.size.height = rect.size.height-100;
            [view setFrame:rect];
            return;
        }
    }

在使用view除錯工具 debug->view debug->capture view hierarchy
檢視UITransitionView;
這裡寫圖片描述

我們能很清楚的看到UITransitionView裡面顯示的是什麼東西(藍色邊框);

接下來分析UITabBar裡面的view 層!!在viewdidappear中加入下面程式碼

 NSLog(@"viewDidAppear");

    for(UIView *view in self.view.subviews){
        if ([view isKindOfClass:NSClassFromString(@"UITabBar")]) {

            CGRect rect = view.frame;
            rect.size.height = 150;
            rect.origin.y = rect.origin.y - 150+49;
            [view setFrame:rect];

            UIView * UITabBarBackgroundView = [view.subviews firstObject];
            UITabBarBackgroundView.backgroundColor = [UIColor yellowColor];
            rect = UITabBarBackgroundView.frame;
            rect.size.height = 150;
            [UITabBarBackgroundView setFrame:rect];

            UIView * UIBackdropView = [UITabBarBackgroundView.subviews firstObject];
            UIBackdropView.backgroundColor = [UIColor greenColor];
            rect = UIBackdropView.frame;
            rect.size.width = 200;
            rect.size.height = 150;
            [UIBackdropView setFrame:rect];

            UIView * UIBackdropEffectView = [UIBackdropView.subviews firstObject];
            UIBackdropEffectView.backgroundColor = [UIColor redColor];
            rect = UIBackdropEffectView.frame;
            rect.size.width = 200;
            rect.size.height = 150;
            [UIBackdropEffectView setFrame:rect];

        }
    }

這裡寫圖片描述

區域3沒有UIBackdropView層,它顯示出了UITabBarBackgroundView的顏色,由此知道了bar的玻璃透明效果是UIBackdropView來控制的,而UIBackdropEffectView層時整個玻璃效果的核心,UIBackdropView的綠色背景,只是在2區域中稍微的顯示了出來,作為一個邊界的漸變效果,至於UIBackdropEffectView內部是怎樣產生的,我們無法得知了。

現在我們把原生tabBar的高度改變了,顏色的產生也明白了,但是好像還有一點問題,barItem的高度和位置應該放在中間吧,於是加入如下程式碼..

for (UIView *subView in view.subviews) {
                if ([subView isKindOfClass:NSClassFromString(@"UITabBarButton")]) {

                    UIView * lableView = [subView.subviews firstObject];
                    CGRect re = lableView.frame;
                    subView.backgroundColor = [UIColor redColor];
                    re.origin.y = subView.frame.size.height/2;
                    [lableView setFrame:re];
                }
            }

然而並沒有什麼卵用,Why? 瞅瞅官方寫的tabBar的文件。有沒有能起作用的。
幾個屬性---

itemPositioning | itemSpacing | itemWidth 貌似可以操作items看看效果吧 加入程式碼

 self.tabBar.itemPositioning = UITabBarItemPositioningCentered;
    self.tabBar.itemSpacing = 20;
    self.tabBar.itemWidth = 20;

這裡寫圖片描述

懂了吧當UITabBarItemPositioningCentered時候,item會向中間靠攏, UITabBarItemPositioningFill就沒有這個效果會直接填滿了整個tabbar 的。。然而這並沒有設定高度的,不甘心,我們接著將items爬出來。。。
在UITabBarItem種我們找到了setTitlePositionAdjustment方法;我們試一下;

 NSArray *Items = self.tabBar.items;
    NSLog(@"link : %@",Items);
    UITabBarItem *item = [Items firstObject];
    [item setTitlePositionAdjustment:UIOffsetMake(0, -20)];

這裡寫圖片描述

嗯 item中的title改變了 。。。

總結:對於TabBar控制元件而言,apple對於其整合度是很高的,所以我們很難再其中加以改動,至於tabbar自己會有自己內部的機制將item有秩序的放在其view內部,在手冊中UITabbarItem的父類UIbarItem並不是UIView的子類,所以起並沒有frame和bonds屬性,這就讓我們很難去改動item的大小了,(然而這並沒有什麼卵用),如果要使用原生的tabbarController的話那麼久應該遵循其規律。。