VTMagic
有很多開發者曾嘗試模仿寫出類似網易、騰訊等應用的菜單分頁組件,但遍觀其設計,大多都比較粗糙,不利于后續維護和擴展。琢磨良久,最終決定開源這個耗時近兩年打磨而成的框架,以便大家可以快速實現類似需求,而不用把大量的精力浪費在重復造輪子的過程中,VTMagic目前在多個項目中穩定運行一年多。
特性概要
- 每個頁面都是一個完整的控制器,友好支持個性化自定義;
- 頁面切換時能準確觸發相應的生命周期方法(
viewWillAppear:
等),便于管理各自頁面的數據加載和其它邏輯處理; - 導航欄支持多種布局樣式,包括自適應文本寬度、自動平分、居中布局以及自定義寬度等;
- 可以在任意子控制器中,通過
self.magicController
獲取最近的上層主控制器,方便跨層級處理邏輯; - 支持內嵌webview,若滑動手勢無法響應,可以通過
handlePanGesture:
解決; - 支持頁面重用和橫豎屏切換;
- 更多特性請參見
VTMagicView.h
文件。
使用
VTMagic支持CocoaPods,只需在Podfile文件中添加如下代碼即可:
pod "VTMagic"
提示:在使用Pod的過程中可能會遇到無法搜到VTMagic的情況,這是因為VTMagic最近才上傳到CocoaPods,你需要更新一下本地的Pod倉庫:$ pod repo udpate
,或者你也可以嘗試一下升級Pod:$ sudo gem install cocoapods
$ pod setup
。
當然,假如你們的項目暫時還不支持Pod,你可以先下載VTMagic,然后再將文件夾VTMagic
拖到你們的項目里面,最后再import頭文件VTMagic.h
即可。
import "VTMagic.h"
集成
關于VTMagic的集成方法主要有以下兩種:
1. 直接實例化VTMagicController對象,然后添加到當前控制器中。
- (void)viewDidLoad
{
[super viewDidLoad];
[self addChildViewController:self.magicController];
[self.view addSubview:_magicController.view];
[_magicController.magicView reloadData];
}
- (VTMagicController *)magicController
{
if (!_magicController) {
_magicController = [[VTMagicController alloc] init];
_magicController.magicView.navigationColor = [UIColor whiteColor];
_magicController.magicView.sliderColor = [UIColor redColor];
_magicController.magicView.layoutStyle = VTLayoutStyleDivide;
_magicController.magicView.switchStyle = VTSwitchStyleDefault;
_magicController.magicView.navigationHeight = 40.f;
_magicController.magicView.dataSource = self;
_magicController.magicView.delegate = self;
}
return _magicController;
}
2. 繼承VTMagicController,然后在viewDidLoad中完成相應配置。
#import "VTMagicController.h"
@interface ViewController : VTMagicController
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.magicView.navigationColor = [UIColor whiteColor];
self.magicView.sliderColor = [UIColor redColor];
self.magicView.layoutStyle = VTLayoutStyleDefault;
self.magicView.switchStyle = VTSwitchStyleDefault;
self.magicView.navigationHeight = 40.f;
self.magicView.dataSource = self;
self.magicView.delegate = self;
[self.magicView reloadData];
}
VTMagicViewDataSource協議
不管是通過以上哪種方法集成的,都需要實現數據源協議< VTMagicViewDataSource >
,主要有以下三個方法:
- (NSArray<NSString *> *)menuTitlesForMagicView:(VTMagicView *)magicView
{
return _menuList;
}
- (UIButton *)magicView:(VTMagicView *)magicView menuItemAtIndex:(NSUInteger)itemIndex
{
static NSString *itemIdentifier = @"itemIdentifier";
UIButton *menuItem = [magicView dequeueReusableItemWithIdentifier:itemIdentifier];
if (!menuItem) {
menuItem = [UIButton buttonWithType:UIButtonTypeCustom];
[menuItem setTitleColor:RGBCOLOR(50, 50, 50) forState:UIControlStateNormal];
[menuItem setTitleColor:RGBCOLOR(169, 37, 37) forState:UIControlStateSelected];
menuItem.titleLabel.font = [UIFont fontWithName:@"Helvetica" size:16.f];
}
return menuItem;
}
- (UIViewController *)magicView:(VTMagicView *)magicView viewControllerAtPage:(NSUInteger)pageIndex
{
if (0 == pageIndex) {
static NSString *recomId = @"recom.identifier";
VTRecomViewController *recomViewController = [magicView dequeueReusablePageWithIdentifier:recomId];
if (!recomViewController) {
recomViewController = [[VTRecomViewController alloc] init];
}
return recomViewController;
}
static NSString *gridId = @"grid.identifier";
VTGridViewController *gridViewController = [magicView dequeueReusablePageWithIdentifier:gridId];
if (!gridViewController) {
gridViewController = [[VTGridViewController alloc] init];
}
return gridViewController;
}
集成效果
重要協議
除了數據源協議< VTMagicViewDataSource >
外 ,VTMagic中的重要協議還有< VTMagicViewDelegate >
和< VTMagicReuseProtocol >
。
VTMagicViewDelegate協議
主要用于在主控制器中處理頁面切換事件。當子頁面顯示或消失時,會觸發viewDidAppeare:
和viewDidDisappeare:
代理方法;當menuItem被點擊時,會觸發didSelectItemAtIndex:
方法。
- (void)magicView:(VTMagicView *)magicView viewDidAppeare:(__kindof UIViewController *)viewController atPage:(NSUInteger)pageIndex
{
NSLog(@"pageIndex:%ld viewDidAppeare:%@",pageIndex, viewController.view);
}
- (void)magicView:(VTMagicView *)magicView viewDidDisappeare:(__kindof UIViewController *)viewController atPage:(NSUInteger)pageIndex
{
NSLog(@"pageIndex:%ld viewDidDisappeare:%@",pageIndex, viewController.view);
}
- (void)magicView:(VTMagicView *)magicView didSelectItemAtIndex:(NSUInteger)itemIndex
{
NSLog(@"didSelectItemAtIndex:%ld", (long)itemIndex);
}
VTMagicReuseProtocol
用于子控制器被重用時,清除舊數據、修正頁面偏移等邏輯處理。
- (void)vtm_prepareForReuse
{
NSLog(@"clear old data if needed:%@", self);
[self.collectionView setContentOffset:CGPointZero];
}
其它
- 你可以在任意子控制器中,通過self.magicController獲取最近的上層主控制器,magicController遵循協議
< VTMagicProtocol >
,以便完成一些必要的跨層級的邏輯處理,前提是你需要import<VTMagic/VTMagic.h>
文件。
NSInteger currentPage = self.magicController.currentPage;
UIViewController *viewController = self.magicController.currentViewController;
- 切換到指定頁面,頁面切換有兩種方式:
[self.magicView switchToPage:3 animated:YES];
[self.magicController switchToPage:3 animated:YES];
- 獲取指定頁面控制器,同樣有兩種方式:
UIViewController *viewController = [self.magicView viewControllerAtPage:3];
UIViewController *viewController = [self.magicController viewControllerAtPage:3];
結束語
最后,按照慣例,如果你喜歡這個輪子,請留下一顆star,這是對作者最大的鼓勵和支持,拜謝!!!假如你有更好的想法或方案,也歡迎提交pull request!!!GitHub地址