自定義放大 TabBar
下面是效果圖:

效果圖
要實現上面的效果方法有好多種,今天我們用原生的UITabBar來做。
注:這裡有一個很小的知識點需要注意一下就是UITabBarItem 是UIBarItem 的子類,直接繼承自其。理解這個有助於更好的理解具體實現。
其實實現起來的大致步驟為:
一、item突出顯示(偏移)
二、item手勢響應處理
item突出顯示(偏移)
第一步很簡單。建立一個UITabBarController並新增子控制器。
.h @interface TabbarVC : UITabBarController @end .m -(void)addControllers{ OneVC *one = [[OneVC alloc]init]; UINavigationController *navOne = [[UINavigationController alloc]initWithRootViewController:one]; navOne.tabBarItem = [self getTabBarItemWithTitle:@"第一個" image:[UIImage imageNamed:@"動態"] selectImage:[UIImage imageNamed:@"動態hober"] tag:1]; TwoVC *two = [[TwoVC alloc]init]; UINavigationController *navTwo = [[UINavigationController alloc]initWithRootViewController:two]; navTwo.tabBarItem = [self getTabBarItemWithTitle:@"第二個" image:[UIImage imageNamed:@"我的"] selectImage:[UIImage imageNamed:@"我的hover"] tag:2]; ThreeVC *three = [[ThreeVC alloc]init]; UINavigationController *navThree = [[UINavigationController alloc]initWithRootViewController:three]; navThree.tabBarItem = [self getTabBarItemWithTitle:@"第三個" image:[UIImage imageNamed:@"展示"] selectImage:[UIImage imageNamed:@"展示hover"] tag:3]; FourVC *four = [[FourVC alloc]init]; UINavigationController *navFour = [[UINavigationController alloc]initWithRootViewController:four]; navFour.tabBarItem = [self getTabBarItemWithTitle:@"第四個" image:[UIImage imageNamed:@"訓練"] selectImage:[UIImage imageNamed:@"訓練hover"] tag:4]; FiveVC *five = [[FiveVC alloc]init]; UINavigationController *navFive = [[UINavigationController alloc]initWithRootViewController:five]; navFive.tabBarItem = [self getTabBarItemWithTitle:@"第四個" image:[UIImage imageNamed:@"收藏灰"] selectImage:[UIImage imageNamed:@"收藏"] tag:5]; self.viewControllers = @[navOne,navTwo,navThree,navFour,navFive]; } -(UITabBarItem *)getTabBarItemWithTitle:(NSString *)title image:(UIImage *)image selectImage:(UIImage *)selectImage tag:(NSInteger)tag{ UITabBarItem *item = [[UITabBarItem alloc]initWithTitle:title image:image tag:tag]; item.selectedImage = selectImage; return item; }
緊接著我們實現UITabBarController 的viewWillLayoutSubviews方法,獲取到自己的tabBar上的指定UITabBarItem ,然後拿到UITabBarItem上的imageView檢視,設定偏移量,並新增點選事件,做出響應事件的處理。
-(void)viewWillLayoutSubviews{ [super viewWillLayoutSubviews]; UITabBarItem *tabbarItem = self.tabBar.items[2]; tabbarItem.imageInsets = UIEdgeInsetsMake(-25, 0, 0, 0); UIImageView *imageView = [tabbarItem lgj_imageView]; if (imageView && !imageView.userInteractionEnabled) { imageView.userInteractionEnabled = YES; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(mittileTap)]; [imageView addGestureRecognizer:tap]; } } -(void)mittileTap{ self.selectedIndex = 2; }
item手勢響應處理
接下來建立UIBarItem、UITabBarItem和UITabBar的分類
UIBarItem+LGJBarItem.h
#import <UIKit/UIKit.h> @interface UIBarItem (LGJBarItem) @property(nonatomic,nullable,weak,readonly)UIView*lgj_view; @end #import "UIBarItem+LGJBarItem.h" @implementation UIBarItem (LGJBarItem) -(UIView *)lgj_view{ return [self valueForKey:@"view"]; } @end
UITabBarItem+LGJBarItem.h
#import <UIKit/UIKit.h> @interface UITabBarItem (LGJTabBarItem) @property(nonatomic, copy) void (^lgj_doubleTapBlock)(UITabBarItem *tabBarItem, NSInteger index); - (UIImageView *)lgj_imageView; + (UIImageView *)lgj_imageViewInTabBarButton:(UIView *)tabBarButton; @end #import "UITabBarItem+LGJTabBarItem.h" #import "UIBarItem+LGJBarItem.h" #import <objc/runtime.h> @implementation UITabBarItem (LGJTabBarItem) - (UIImageView *)lgj_imageView { return [self.class lgj_imageViewInTabBarButton:self.lgj_view]; } + (UIImageView *)lgj_imageViewInTabBarButton:(UIView *)tabBarButton { if (!tabBarButton ) { return nil; } for (UIView *subView in tabBarButton.subviews) { if ([NSStringFromClass([subView class]) isEqualToString:@"UITabBarSwappableImageView"]) { return (UIImageView *)subView; } NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; CFShow(CFBridgingRetain(infoDictionary)); NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"]; float version = [app_Version floatValue]; if (version < 10) { // iOS10以前,選中的item的高亮是用UITabBarSelectionIndicatorView實現的,所以要遮蔽掉 if ([subView isKindOfClass:[UIImageView class]] && ![NSStringFromClass([subView class]) isEqualToString:@"UITabBarSelectionIndicatorView"]) { return (UIImageView *)subView; } } } return nil; } static char kAssociatedObjectKey_doubleTapBlock; - (void)setLgj_doubleTapBlock:(void (^)(UITabBarItem *, NSInteger))gs_doubleTapBlock { objc_setAssociatedObject(self, &kAssociatedObjectKey_doubleTapBlock, gs_doubleTapBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (void (^)(UITabBarItem *, NSInteger))lgj_doubleTapBlock { return (void (^)(UITabBarItem *, NSInteger))objc_getAssociatedObject(self, &kAssociatedObjectKey_doubleTapBlock); } @end
UITabBar+LGJBarItem.h
#import <UIKit/UIKit.h> @interface UITabBar (LGJTabBar) @end #import "UITabBar+LGJTabBar.h" #import "UITabBarItem+LGJTabBarItem.h" @implementation UITabBar (LGJTabBar) - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (!self.isUserInteractionEnabled || self.isHidden || self.alpha <= 0.01) { return nil; } if (self.items.count < 2) { return [super hitTest:point withEvent:event]; } UITabBarItem *item = self.items[2]; UIImageView *itemImageView = [item lgj_imageView]; if (!itemImageView) { return [super hitTest:point withEvent:event]; } UIView *view = [super hitTest:point withEvent:event]; if (view == nil){ //轉換座標 CGPoint tempPoint = [itemImageView convertPoint:point fromView:self]; //判斷點選的點是否在按鈕區域內 if (CGRectContainsPoint(itemImageView.bounds, tempPoint)){ //返回按鈕 return itemImageView; } //****************** 或者使用這個方法 **************** //判斷如果這個新的點是在釋出按鈕身上,那麼處理點選事件最合適的view就是釋出按鈕 if ([itemImageView pointInside:point withEvent:event]) { return itemImageView; }else{ //如果點不在釋出按鈕身上,直接讓系統處理就可以了 return [super hitTest:point withEvent:event]; } } return view; } @end
以上工作完成,一個突出的TabBar就出現了,,,,