iOS自定义TabBarViewController

来源:互联网 发布:淘宝女装行业退款率 编辑:程序博客网 时间:2024/05/23 12:23

UITabBarController 虽然很强大,基本上也能满足常见的需求,但是用起来总没那么畅快。有时候,总有一些变态的需求,需要自定义。

之前也看过一些别人自定义的TabBarController,但是都不尽理想,准确的说,很多自定义的都是继承自UITabBarController的即是半自定义的。根本谈不上真正意义上的自定义。

今天就分析一个我认为比较好的自定义TabBarController.

一,先来看一下TabBarController的基本结构

一般说来TabBarController,下面有一个TabBar, TabBar是一个视图,继承自UIView.
TabBar这个视图里面又有多个选项TabBarItem,这些个Item,是一个可以点击,并且可以切换到对应的控制器页面的按键,同时,这些按键还有自己本身的属性设置。所以Item应该继承自UIControl. 所以结构就很清楚了:分3个部分。
  • TabBarController (继承自UIViewController)
  • TabBar    (继承自UIView)
  • TabBarItem       (继承自UIControl)

二,分别来封装和分析各个部分

1. 先来看TabBarItem

tabBarItem,直观的显示,就是我们看到那几个点击来回切换的按键。当点击每一个选项的时候,选项就会有相应的变化,同时切换到对应的控制器界面。
有哪些属性和变化呢?

  a. 本身基本属性:有选中/未选中图片、选中/未选中文字及颜色、选中/未选中背景色、有宽高大小位置偏移(供微调用);

  b. 徽标显示:徽标值及其颜色大小、徽标图片、背景色

  

#import <UIKit/UIKit.h>@interface RDVTabBarItem : UIControl/** * itemHeight is an optional property. When set it is used instead of tabBar's height. */@property CGFloat itemHeight;#pragma mark - Title configuration/** * The title displayed by the tab bar item. */@property (nonatomic, copy) NSString *title;/** * The offset for the rectangle around the tab bar item's title. */@property (nonatomic) UIOffset titlePositionAdjustment;/** * For title's text attributes see * https://developer.apple.com/library/ios/documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html *//** * The title attributes dictionary used for tab bar item's unselected state. */@property (copy) NSDictionary *unselectedTitleAttributes;/** * The title attributes dictionary used for tab bar item's selected state. */@property (copy) NSDictionary *selectedTitleAttributes;#pragma mark - Image configuration/** * The offset for the rectangle around the tab bar item's image. */@property (nonatomic) UIOffset imagePositionAdjustment;/** * The image used for tab bar item's selected state. */- (UIImage *)finishedSelectedImage;/** * The image used for tab bar item's unselected state. */- (UIImage *)finishedUnselectedImage;/** * Sets the tab bar item's selected and unselected images. */- (void)setFinishedSelectedImage:(UIImage *)selectedImage withFinishedUnselectedImage:(UIImage *)unselectedImage;#pragma mark - Background configuration/** * The background image used for tab bar item's selected state. */- (UIImage *)backgroundSelectedImage;/** * The background image used for tab bar item's unselected state. */- (UIImage *)backgroundUnselectedImage;/** * Sets the tab bar item's selected and unselected background images. */- (void)setBackgroundSelectedImage:(UIImage *)selectedImage withUnselectedImage:(UIImage *)unselectedImage;#pragma mark - Badge configuration/** * Text that is displayed in the upper-right corner of the item with a surrounding background. */@property (nonatomic, copy) NSString *badgeValue;/** * Image used for background of badge. */@property (strong) UIImage *badgeBackgroundImage;/** * Color used for badge's background. */@property (strong) UIColor *badgeBackgroundColor;/** * Color used for badge's text. */@property (strong) UIColor *badgeTextColor;/** * The offset for the rectangle around the tab bar item's badge. */@property (nonatomic) UIOffset badgePositionAdjustment;/** * Font used for badge's text. */@property (nonatomic) UIFont *badgeTextFont;@end

2. 再来看TabBar

tabBar是一个视图,自然有视图的基本属性,里面有多个tabBarItem,所以必然有items个数的属性;有事件响应,所以有代理抛出接口

#import <UIKit/UIKit.h>@class RDVTabBar, RDVTabBarItem;@protocol RDVTabBarDelegate <NSObject>/** * Asks the delegate if the specified tab bar item should be selected. */- (BOOL)tabBar:(RDVTabBar *)tabBar shouldSelectItemAtIndex:(NSInteger)index;/** * Tells the delegate that the specified tab bar item is now selected. */- (void)tabBar:(RDVTabBar *)tabBar didSelectItemAtIndex:(NSInteger)index;@end@interface RDVTabBar : UIView/** * The tab bar’s delegate object. */@property (nonatomic, weak) id <RDVTabBarDelegate> delegate;/** * The items displayed on the tab bar. */@property (nonatomic, copy) NSArray *items;/** * The currently selected item on the tab bar. */@property (nonatomic, weak) RDVTabBarItem *selectedItem;/** * backgroundView stays behind tabBar's items. If you want to add additional views,  * add them as subviews of backgroundView. */@property (nonatomic, readonly) UIView *backgroundView;/* * contentEdgeInsets can be used to center the items in the middle of the tabBar. */@property UIEdgeInsets contentEdgeInsets;/** * Sets the height of tab bar. */- (void)setHeight:(CGFloat)height;/** * Returns the minimum height of tab bar's items. */- (CGFloat)minimumContentHeight;/* * Enable or disable tabBar translucency. Default is NO. */@property (nonatomic, getter=isTranslucent) BOOL translucent;@end

3. 最后来看TabBarController

TabBarController 里面有TabBar, 有默认选项,tabBarItem对应的View Controllers及其之间的关联。还有一些代理方法。故而

#import <UIKit/UIKit.h>#import "RDVTabBar.h"@protocol RDVTabBarControllerDelegate;@interface RDVTabBarController : UIViewController <RDVTabBarDelegate>/** * The tab bar controller’s delegate object. */@property (nonatomic, weak) id<RDVTabBarControllerDelegate> delegate;/** * An array of the root view controllers displayed by the tab bar interface. */@property (nonatomic, copy) IBOutletCollection(UIViewController) NSArray *viewControllers;/** * The tab bar view associated with this controller. (read-only) */@property (nonatomic, readonly) RDVTabBar *tabBar;/** * The view controller associated with the currently selected tab item. */@property (nonatomic, weak) UIViewController *selectedViewController;/** * The index of the view controller associated with the currently selected tab item. */@property (nonatomic) NSUInteger selectedIndex;/** * A Boolean value that determines whether the tab bar is hidden. */@property (nonatomic, getter=isTabBarHidden) BOOL tabBarHidden;/** * Changes the visibility of the tab bar. */- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated;@end@protocol RDVTabBarControllerDelegate <NSObject>@optional/** * Asks the delegate whether the specified view controller should be made active. */- (BOOL)tabBarController:(RDVTabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;/** * Tells the delegate that the user selected an item in the tab bar. */- (void)tabBarController:(RDVTabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;@end@interface UIViewController (RDVTabBarControllerItem)/** * The tab bar item that represents the view controller when added to a tab bar controller. */@property(nonatomic, setter = rdv_setTabBarItem:) RDVTabBarItem *rdv_tabBarItem;/** * The nearest ancestor in the view controller hierarchy that is a tab bar controller. (read-only) */@property(nonatomic, readonly) RDVTabBarController *rdv_tabBarController;@end

重点分析一下,当点击TabBarItem的时候,如何关联控制器的。

其实就是通过导航控制器来切换到对应编号的视图控制器。请看核心代码

- (BOOL)tabBar:(RDVTabBar *)tabBar shouldSelectItemAtIndex:(NSInteger)index {    if ([[self delegate] respondsToSelector:@selector(tabBarController:shouldSelectViewController:)]) {        if (![[self delegate] tabBarController:self shouldSelectViewController:[self viewControllers][index]]) {            return NO;        }    }        if ([self selectedViewController] == [self viewControllers][index]) {        if ([[self selectedViewController] isKindOfClass:[UINavigationController class]]) {            UINavigationController *selectedController = (UINavigationController *)[self selectedViewController];                        if ([selectedController topViewController] != [selectedController viewControllers][0]) {                [selectedController popToRootViewControllerAnimated:YES];            }        }                return NO;    }        return YES;}

三,代码部分

限于篇幅,不直接贴出代码,

直接获取源码Demo:https://github.com/robbdimitrov/RDVTabBarController

0 0
原创粉丝点击