AMKTabView
Introduction
在 iOS 开发中,UITabBar 是一个非常常用的控件,以便实现多页面的点击切换; 在 MacOS 中则是通过 NSTabView 来实现,但不是那么好看,所以作者参考Mac端微信、QQ客户端,结合iOS开发经验,参考 UITabBar 类的接口设计,开发了这个 AMKTabView,以便在MacOS中使用类似 UITabBar 的控件。
AMKTabViewController.h
![]() |
![]() |
![]() |
![]() |
---|---|---|---|
AMKTabPositionTop | AMKTabPositionLeft | AMKTabPositionBottom | AMKTabPositionRight |
AMKWechatTabViewController.h
![]() |
![]() |
![]() |
---|---|---|
消息Tab | 联系人Tab | 收藏Tab |
Features
使用该库,可以实现:
- 可快速创建一个类似 UITabBar 的视图,提供方便、优雅的事件回调,并支持深度自定义布局,甚至扩展;
- 可快速创建一个类似 UITabBarController 的页面;
- 可快速创建一个类似微信MacOS客户端的APP框架,开发自己的MacApp;
Example
To run the example project, clone the repo, and run pod install
from the Example directory first.
Requirements
- MacOS 10.10+
Installation
AMKTabView is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'AMKTabView'
Usage
#import <AMKTabView/AMKTabView.h>
1. Interface 接口设计
/// AMKTabView的位置
typedef NS_ENUM(NSUInteger, AMKTabPosition) {
AMKTabPositionNone = 0,
AMKTabPositionTop = 1,
AMKTabPositionLeft = 2,
AMKTabPositionBottom = 3,
AMKTabPositionRight = 4
};
/// AMKTabView
@interface AMKTabView : NSView
@property(nonatomic, assign) AMKTabPosition tabPosition; //!< TabView的位置
@property(nonatomic, strong, nullable) NSView *contentView; //!< 主内容视图
@property(nonatomic, assign, nullable) id<AMKTabViewDelegate> delegate; //!< 代理
@property(nonatomic, strong, nullable) AMKTabViewItem *selectedTabViewItem; //!< 当前选中的可点击项
@property(nonatomic, copy, nullable) NSArray<__kindof AMKTabViewItem *> *tabViewItems; //!< 所有可点击项
- (void)addTabViewItem:(AMKTabViewItem *)tabViewItem; //!< 在后面追加可点击项
- (void)insertTabViewItem:(AMKTabViewItem *)tabViewItem atIndex:(NSInteger)index; //!< 在指定位置插入可点击项
- (void)removeTabViewItem:(AMKTabViewItem *)tabViewItem; //!< 删除指定位置的可点击项
- (NSInteger)numberOfTabViewItems; //!< 所有可点击项的数量
- (NSInteger)indexOfTabViewItem:(AMKTabViewItem *_Nullable)tabViewItem; //!< 指定可点击项的下标
- (AMKTabViewItem *_Nullable)tabViewItemAtIndex:(NSInteger)index; //!< 返回指定下标的可点击项
- (void)selectTabViewItem:(AMKTabViewItem *_Nullable)tabViewItem; //!< 选中指定可点击项
- (void)selectTabViewItemAtIndex:(NSInteger)index; //!< 选中指定下标的可点击项
- (void)selectFirstTabViewItem:(id _Nullable)sender; //!< 选中第一个的可点击项
- (void)selectLastTabViewItem:(id _Nullable)sender; //!< 选中最后一个的可点击项
- (void)selectNextTabViewItem:(id _Nullable)sender; //!< 选中当前指定下标的后一个可点击项
- (void)selectPreviousTabViewItem:(id _Nullable)sender; //!< 选中当前指定下标的前一个可点击项
@end
/// 可子类重写的方法
@interface AMKTabView (AMKSubclassing)
- (void)relayoutTabViewItems; //!< 重新布局 tabViewItems
@end
/// AMKTabView 代理
@protocol AMKTabViewDelegate <NSObject>
@optional
- (BOOL)tabView:(AMKTabView *_Nullable)tabView shouldSelectTabViewItem:(AMKTabViewItem *_Nullable)tabViewItem;
- (void)tabView:(AMKTabView *_Nullable)tabView willSelectTabViewItem:(AMKTabViewItem *_Nullable)tabViewItem;
- (void)tabView:(AMKTabView *_Nullable)tabView didSelectTabViewItem:(AMKTabViewItem *_Nullable)tabViewItem;
- (void)tabViewDidChangeNumberOfTabViewItems:(AMKTabView *_Nullable)tabView;
@end
Coding 编码示例
- (AMKTabView *)tabView {
if (!_tabView) {
_tabView = [AMKTabView.alloc init];
_tabView.wantsLayer = YES;
_tabView.layer.backgroundColor = [NSColor colorWithRed:0.27 green:0.62 blue:0.89 alpha:1.00].CGColor;
_tabView.contentView = [NSView.alloc init];
_tabView.contentView.wantsLayer = YES;
_tabView.contentView.layer.backgroundColor = [NSColor colorWithRed:0.98 green:0.87 blue:0.30 alpha:1.00].CGColor;
_tabView.delegate = self;
[self.view addSubview:_tabView];
[self.view addSubview:_tabView.contentView];
}
return _tabView;
}
#import <AMKTabView/AMKTabViewController.h>
2. #import <AMKTabView/AMKTabViewController.h>
/// AMKTabViewController 示例
@interface AMKExampleTabViewController : AMKTabViewController
@end
@implementation AMKExampleTabViewController
- (void)loadView {
self.view = [NSView.alloc init];
[self.tabView selectTabViewItemAtIndex:0];
}
- (AMKTabView *)tabView {
if (!_tabView) {
_tabView = [super tabView];
_tabView.wantsLayer = YES;
_tabView.tabPosition = AMKTabPositionRight;
_tabView.layer.backgroundColor = [NSColor colorWithRed:0.18 green:0.18 blue:0.18 alpha:1.00].CGColor;
_tabView.contentView.wantsLayer = YES;
_tabView.contentView.layer.backgroundColor = [NSColor colorWithRed:0.20 green:0.20 blue:0.20 alpha:1.00].CGColor;
[_tabView addTabViewItem:({
AMKTabViewItem *tabViewItem =
[AMKTabViewItem tabViewItemWithImage:[NSImage imageNamed:@"amk_root_tab_message_n"] selectedImage:[NSImage imageNamed:@"amk_root_tab_message_s"]];
tabViewItem.contentViewController = [AMKContentViewController.alloc init];
tabViewItem.contentViewController.title = @"消息";
tabViewItem.toolTip = tabViewItem.contentViewController.title;
tabViewItem;
})];
[_tabView addTabViewItem:({
AMKTabViewItem *tabViewItem =
[AMKTabViewItem tabViewItemWithImage:[NSImage imageNamed:@"amk_root_tab_contact_n"] selectedImage:[NSImage imageNamed:@"amk_root_tab_contact_s"]];
tabViewItem.contentViewController = [AMKContentViewController.alloc init];
tabViewItem.contentViewController.title = @"联系人";
tabViewItem.toolTip = tabViewItem.contentViewController.title;
tabViewItem;
})];
[_tabView addTabViewItem:({
AMKTabViewItem *tabViewItem =
[AMKTabViewItem tabViewItemWithImage:[NSImage imageNamed:@"amk_root_tab_collection_n"] selectedImage:[NSImage imageNamed:@"amk_root_tab_collection_s"]];
tabViewItem.contentViewController = [AMKContentViewController.alloc init];
tabViewItem.contentViewController.title = @"收藏";
tabViewItem.toolTip = tabViewItem.contentViewController.title;
tabViewItem;
})];
[self relayoutTabView];
}
return _tabView;
}
#pragma mark AMKTabViewDelegate
- (BOOL)tabView:(AMKTabView *)tabView shouldSelectTabViewItem:(nullable AMKTabViewItem *)tabViewItem {
NSLog(@"%@", tabViewItem.toolTip);
return tabView.selectedTabViewItem == tabViewItem ? NO : YES;
}
- (void)tabView:(AMKTabView *)tabView willSelectTabViewItem:(nullable AMKTabViewItem *)tabViewItem {
NSLog(@"%@", tabViewItem.toolTip);
}
- (void)tabView:(AMKTabView *)tabView didSelectTabViewItem:(nullable AMKTabViewItem *)tabViewItem {
NSLog(@"%@", tabViewItem.toolTip);
}
- (void)tabViewDidChangeNumberOfTabViewItems:(AMKTabView *)tabView {
NSLog(@"%@", tabView.tabViewItems);
}
@end
#import <AMKTabView/AMKWechatTabView.h>
仿微信Mac客户端TabView
3. Coding
- (AMKWechatTabView *)tabView {
if (!_tabView) {
_tabView = [AMKWechatTabView.alloc init];
_tabView.wantsLayer = YES;
_tabView.layer.backgroundColor = [NSColor colorWithRed:0.27 green:0.62 blue:0.89 alpha:1.00].CGColor;
_tabView.contentView = [NSView.alloc init];
_tabView.contentView.wantsLayer = YES;
_tabView.contentView.layer.backgroundColor = [NSColor colorWithRed:0.98 green:0.87 blue:0.30 alpha:1.00].CGColor;
_tabView.delegate = self;
[self.view addSubview:_tabView];
[self.view addSubview:_tabView.contentView];
}
return _tabView;
}
#import <AMKTabView/AMKWechatTabViewController.h>
仿微信Mac客户端TabView
4. #import "AMKWechatTabViewController.h"
@interface AMKExampleWechatTabViewController : AMKWechatTabViewController
@end
@implementation AMKExampleWechatTabViewController
- (void)loadView {
self.view = [NSView.alloc init];
[self.tabView selectTabViewItemAtIndex:0];
}
- (AMKWechatTabView *)tabView {
if (!_tabView) {
_tabView = [super tabView];
_tabView.wantsLayer = YES;
_tabView.layer.backgroundColor = [NSColor colorWithRed:0.13 green:0.12 blue:0.13 alpha:1.00].CGColor;
_tabView.contentView.wantsLayer = YES;
_tabView.contentView.layer.backgroundColor = [NSColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.00].CGColor;
_tabView.profileButton.image = [NSImage imageNamed:@"AppIcon"];
_tabView.menuButton.image = [NSImage imageNamed:@"amk_root_tab_menu_n"];
_tabView.menuButton.alternateImage = [NSImage imageNamed:@"amk_root_tab_menu_s"];
[_tabView addTabViewItem:({
AMKTabViewItem *tabViewItem =
[AMKTabViewItem tabViewItemWithImage:[NSImage imageNamed:@"amk_root_tab_message_n"] selectedImage:[NSImage imageNamed:@"amk_root_tab_message_s"]];
tabViewItem.contentViewController = [AMKContentViewController.alloc init];
tabViewItem.contentViewController.title = @"消息";
tabViewItem.toolTip = tabViewItem.contentViewController.title;
tabViewItem;
})];
[_tabView addTabViewItem:({
AMKTabViewItem *tabViewItem =
[AMKTabViewItem tabViewItemWithImage:[NSImage imageNamed:@"amk_root_tab_contact_n"] selectedImage:[NSImage imageNamed:@"amk_root_tab_contact_s"]];
tabViewItem.contentViewController = [AMKContentViewController.alloc init];
tabViewItem.contentViewController.title = @"联系人";
tabViewItem.toolTip = tabViewItem.contentViewController.title;
tabViewItem;
})];
[_tabView addTabViewItem:({
AMKTabViewItem *tabViewItem =
[AMKTabViewItem tabViewItemWithImage:[NSImage imageNamed:@"amk_root_tab_collection_n"] selectedImage:[NSImage imageNamed:@"amk_root_tab_collection_s"]];
tabViewItem.contentViewController = [AMKContentViewController.alloc init];
tabViewItem.contentViewController.title = @"收藏";
tabViewItem.toolTip = tabViewItem.contentViewController.title;
tabViewItem;
})];
[self relayoutTabView];
}
return _tabView;
}
#pragma mark AMKWechatTabViewDelegate
- (void)tabView:(AMKWechatTabView *_Nullable)tabView didClickProfileButton:(NSButton *_Nullable)profileButton {
NSLog(@"%@", profileButton.toolTip);
}
- (void)tabView:(AMKWechatTabView *_Nullable)tabView didClickMenuButton:(NSButton *_Nullable)menuButton {
NSLog(@"%@", menuButton.toolTip);
}
- (BOOL)tabView:(AMKWechatTabView *)tabView shouldSelectTabViewItem:(nullable AMKTabViewItem *)tabViewItem {
NSLog(@"%@", tabViewItem.toolTip);
return tabView.selectedTabViewItem == tabViewItem ? NO : YES;
}
- (void)tabView:(AMKWechatTabView *)tabView willSelectTabViewItem:(nullable AMKTabViewItem *)tabViewItem {
NSLog(@"%@", tabViewItem.toolTip);
}
- (void)tabView:(AMKWechatTabView *)tabView didSelectTabViewItem:(nullable AMKTabViewItem *)tabViewItem {
NSLog(@"%@", tabViewItem.toolTip);
}
- (void)tabViewDidChangeNumberOfTabViewItems:(AMKWechatTabView *)tabView {
NSLog(@"%@", tabView.tabViewItems);
}
@end
Author
AndyM129, [email protected]
License
AMKTabView is available under the MIT license. See the LICENSE file for more info.