級(jí)別: ★★☆☆☆
標(biāo)簽:「iOS」「分頁」「QiPageMenuView」
作者: 沐靈洛
審校: QiShare團(tuán)隊(duì)
iOS 快速實(shí)現(xiàn)分頁界面的搭建
項(xiàng)目中我們經(jīng)常會(huì)遇到滾動(dòng)分頁的設(shè)計(jì)效果,被用來對(duì)不同數(shù)據(jù)界面的展示進(jìn)行分類。我們先可以來預(yù)覽一下實(shí)現(xiàn)效果:
實(shí)現(xiàn)分析
根據(jù)動(dòng)圖進(jìn)行實(shí)現(xiàn)分析:這個(gè)效果的實(shí)現(xiàn)分為兩部分頂部的QiPageMenuView和內(nèi)容展示部分QiPageContentView:
QiPageMenuView是基于UIScrollView實(shí)現(xiàn)的,我們可以按照自己的項(xiàng)目需求,定制自己需要實(shí)現(xiàn)的效果。QiPageMenuView提供了可設(shè)置的屬性有:菜單每一項(xiàng)是否根據(jù)文字的大小自適應(yīng)寬度還是設(shè)置固定寬度、菜單的首項(xiàng)和最后一項(xiàng)距離父視圖的間距、每一項(xiàng)之間的間距、包括了每一項(xiàng)QiPageItem的展示效果自定義等。也實(shí)現(xiàn)了菜單項(xiàng)超出一屏幕時(shí)自動(dòng)滑動(dòng)顯示的效果:
QiPageContentView是基于UIPageViewController實(shí)現(xiàn)的封裝,在項(xiàng)目中可能有多處這樣的界面效果。單純的使用UIPageViewController寫在相應(yīng)的控制器中,添加相應(yīng)的子控制器,通過實(shí)現(xiàn)UIPageViewController的數(shù)據(jù)源和代理協(xié)議也可以達(dá)到這種效果。但是UIPageViewController嵌套在主控制器中,耦合度比較高,代碼量也比較大,若是多處需要使用這種效果,每次都寫一遍UIPageViewController,效率和可移植性不高。 QiPageMenuView和QiPageContentView之間是解耦合的,彼此都可以作為單獨(dú)的控件去使用。在設(shè)計(jì)構(gòu)思時(shí),菜單視圖的樣式有可能是QiPageMenuView樣式之外的視圖,若是兩者耦合度太高,就變成了QiPageContentView + QiPageMenuView組合,能展現(xiàn)的效果就被限制了。
QiPageMenuView實(shí)現(xiàn)與使用
QiPageMenuView.h中展現(xiàn)了QiPageMenuView可實(shí)現(xiàn)定制的相關(guān)屬性以及初始化方法介紹。@interface QiPageMenuView : UIScrollView<QiPageControllerDelegate>
/**菜單欄點(diǎn)擊事件*/
@property (nonatomic,copy)void(^pageItemClicked)(NSInteger clickedIndex,QiPageMenuView *menu);
/**常態(tài)item的字體顏色*/
@property (nonatomic,strong)UIColor *normalTitleColor;
/**選中item的字體顏色*/
@property (nonatomic,strong)UIColor *selectedTitleColor;
/**常態(tài)item的字體*/
@property (nonatomic,strong)UIFont *titleFont;
/**選中Item的字體*/
@property (nonatomic,strong)UIFont *selectedTitleFont;
/**字體距離item兩邊的間距,itemsAutoResizing = YES時(shí) 設(shè)置有效*/
@property (nonatomic,assign)CGFloat itemTitlePadding;
/**item距上的間距。itemIsVerticalCentred = NO的時(shí)候設(shè)置有效*/
@property (nonatomic,assign)CGFloat itemTopPadding;
/**items的左邊縮進(jìn)*/
@property (nonatomic,assign)CGFloat leftMargin;
/**items的右邊縮進(jìn)*/
@property (nonatomic,assign)CGFloat rightMargin;
/**是否根據(jù)文字的長(zhǎng)度自動(dòng)計(jì)算item的width default YES*/
@property (nonatomic,assign)BOOL itemsAutoResizing;
/**item是否垂直居中顯示,默認(rèn)yes; itemTopPadding 與 lineTopPadding 不會(huì)生效;設(shè)置NO itemHeight會(huì)自適應(yīng)高*/
@property (nonatomic,assign)BOOL itemIsVerticalCentred;
/**item之間的間距*/
@property (nonatomic,assign)CGFloat itemSpace;
/**每個(gè)item的高度*/
@property (nonatomic,assign)CGFloat itemHeight;
/**每個(gè)item的寬度。itemsAutoResizing = YES不必賦值也可。反之必須給值。*/
@property (nonatomic,assign)CGFloat itemWidth;
/**是否顯示下劃線 default YES*/
@property (nonatomic,assign)BOOL hasUnderLine;
/**下劃線顏色*/
@property (nonatomic,strong)UIColor *lineColor;
/**下劃線到item的間距*/
@property (nonatomic,assign)CGFloat lineTopPadding;
/**下劃線的高度*/
@property (nonatomic,assign)CGFloat lineHeight;
/**下劃線的寬度*/
@property (nonatomic,assign)CGFloat lineWitdh;
/**pageController滑動(dòng)完成*/
@property (nonatomic,assign)NSInteger pageScrolledIndex;
/**初始化方法*/
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles dataSource:(NSDictionary<QiPageMenuViewDataSourceKey, id> *)dataSource;
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles;
/**滑動(dòng)到某一項(xiàng) @param pageItem item*/
- (void)scrollToPageItem:(QiPageItem*)pageItem;
/*!@brief 更新標(biāo)題數(shù)組@param items selectedIndex重置選中的item*/
- (void)updateMenuViewWithNewItemArray:(NSArray *)items selectedIndex:(NSInteger)selectedIndex;
@end
復(fù)制代碼QiPageMenuView滑動(dòng)顯示的核心代碼- (void)scrollToPageItem:(QiPageItem*)pageItem {[self refreshUnderLineViewPosition:pageItem];
if (self.contentSize.width <= self.width) {
return;}CGRect originalRect = pageItem.frame;CGRect convertRect = [self convertRect:originalRect toView:self.superview];CGFloat targetX;CGFloat realMidX = CGRectGetM
inX(originalRect)+CGRectGetWidth(originalRect)/2;
if (CGRectGetMidX(convertRect) < CGRectGetMidX(self.frame)) {//是否需要右滑
if (realMidX> CGRectGetMidX(self.frame)) {targetX = realMidX-CGRectGetMidX(self.frame);}
else {targetX = 0;}[self
setContentOffset:CGPointMake(targetX, 0) animated:YES];}
else if (CGRectGetMidX(convertRect) > CGRectGetMidX(self.frame)) {
if (realMidX+CGRectGetMidX(self.frame)<self.contentSize.width) {targetX = realMidX-CGRectGetMidX(self.frame);}
else {targetX = self.contentSize.width - CGRectGetMaxX(self.frame);}[self
setContentOffset:CGPointMake(targetX, 0) animated:YES];}
}
復(fù)制代碼QiPageMenuView使用的兩種方式 //定制樣式NSDictionary *dataSource = @{QiPageMenuViewNormalTitleColor : [UIColor blackColor],QiPageMenuViewSelectedTitleColor : [UIColor redColor],QiPageMenuViewTitleFont : [UIFont systemFontOfSize:14],QiPageMenuViewSelectedTitleFont : [UIFont systemFontOfSize:14],QiPageMenuViewItemIsVerticalCentred : @(YES),QiPageMenuViewItemTitlePadding : @(10.0),QiPageMenuViewItemTopPadding : @(20.0),QiPageMenuViewItemPadding : @(10.0),QiPageMenuViewLeftMargin : @(20.0),QiPageMenuViewRightMargin : @(20.0),QiPageMenuViewItemsAutoResizing : @(YES),QiPageMenuViewItemWidth : @(90.0),QiPageMenuViewItemHeight : @(40.0),QiPageMenuViewHasUnderLine :@(YES),QiPageMenuViewLineColor : [UIColor greenColor],QiPageMenuViewLineWidth : @(30.0),QiPageMenuViewLineHeight : @(4.0),QiPageMenuViewLineTopPadding : @(10.0)};QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) titles:@[@
"消息",@
"節(jié)日消息",@
"廣播通知",@
"QISHARE",@
"奇舞團(tuán)"] dataSource:dataSource];menuView.backgroundColor = [UIColor orangeColor];[self.view addSubview:menuView];
復(fù)制代碼 QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) titles:@[@
"系統(tǒng)消息",@
"節(jié)日消息",@
"廣播通知"]];menuView.backgroundColor = [UIColor orangeColor];//定制樣式menuView.normalTitleColor = [UIColor blackColor];menuView.selectedTitleColor = [UIColor redColor];menuView.titleFont = [UIFont systemFontOfSize:14];menuView.selectedTitleFont = [UIFont systemFontOfSize:14];menuView.itemIsVerticalCentred = YES;menuView.itemTitlePadding = 10.0;menuView.itemTopPadding = 20.0;menuView.itemSpace = 10.0;menuView.leftMargin = 20.0;menuView.rightMargin = 20.0;menuView.itemsAutoResizing = YES;menuView.itemWidth = 90;menuView.itemHeight = 40;menuView.hasUnderLine = YES;menuView.lineColor = [UIColor greenColor];menuView.lineWitdh = 30;menuView.lineHeight = 4.0;menuView.lineTopPadding = 10;[self.view addSubview:menuView];
復(fù)制代碼QiPageContentView實(shí)現(xiàn)與使用
QiPageContentView.h
@interface QiPageContentView : UIView<UIPageViewControllerDelegate, UIPageViewControllerDataSource,UIScrollViewDelegate>@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *controllerArray; //!< 控制器數(shù)組
/**滑動(dòng)結(jié)束:block回調(diào)*/
@property (nonatomic,copy)void(^pageContentViewDidScroll)(NSInteger currentIndex,NSInteger beforeIndex,QiPageContentView *pageView);/**滑動(dòng)結(jié)束:代理回調(diào) 若實(shí)現(xiàn)block代理不會(huì)走*/
@property (nonatomic, weak) id<QiPageContentViewDelegate> contentViewDelgate;/**設(shè)置滑動(dòng)至某一個(gè)控制器@param index index@param beforeIndex 控制方向*/
- (void)
setPageContentShouldScrollToIndex:(NSInteger)index beforIndex:(NSInteger)beforeIndex;/**初始化方法@param frame frame@param childViewControllers childViewControllers@
return 實(shí)例*/
- (instancetype)initWithFrame:(CGRect)frame childViewController:(NSArray*)childViewControllers;@end
復(fù)制代碼QiPageContentView使用QiPageContentView *contenView = [[QiPageContentView alloc]initWithFrame:CGRectMake(0, 10, self.view.width, self.view.height - 88-10) childViewController:@[ctrl,ctrl1,ctrl2,ctrl3]];
[self.view addSubview:contenView];
復(fù)制代碼QiPageContentView與QiPageMenuView解耦
QiPageContentView與QiPageMenuView使用各自頭文件中定義的協(xié)議或者block屬性實(shí)現(xiàn)兩者之間事件交互,從而達(dá)到分頁聯(lián)動(dòng)效果;兩者的解耦,使得它們的使用更加靈活。
QiPageMenuView交互事件的傳遞@protocol QiPageMenuViewDelegate <NSObject>
/**菜單點(diǎn)擊了某個(gè)item@param index 點(diǎn)擊了index*/
- (void)pageMenuViewDidClickedIndex:(NSInteger)index beforeIndex:(NSInteger)beforeIndex;@end@interface QiPageMenuView : UIScrollView
/**菜單欄點(diǎn)擊事件:block回調(diào)*/
@property (nonatomic,copy)void(^pageItemClicked)(NSInteger clickedIndex,NSInteger beforeIndex,QiPageMenuView *menu);/**菜單欄點(diǎn)擊事件:代理回調(diào) 若實(shí)現(xiàn)block代理不會(huì)走*/
@property (nonatomic, weak) id<QiPageMenuViewDelegate> menuViewDelgate;
復(fù)制代碼QiPageContentView交互事件的傳遞@protocol QiPageContentViewDelegate <NSObject>/**滑動(dòng)完成回調(diào)@param index 滑動(dòng)至index*/
- (void)pageContentViewDidScrollToIndex:(NSInteger)index beforeIndex:(NSInteger)beforeIndex;
@end@interface QiPageContentView : UIView<UIPageViewControllerDelegate, UIPageViewControllerDataSource,UIScrollViewDelegate>
@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *controllerArray; //!< 控制器數(shù)組
/**滑動(dòng)結(jié)束:block回調(diào)*/
@property (nonatomic,copy)void(^pageContentViewDidScroll)(NSInteger currentIndex,NSInteger beforeIndex,QiPageContentView *pageView);
/**滑動(dòng)結(jié)束:代理回調(diào) 若實(shí)現(xiàn)block代理不會(huì)走*/
@property (nonatomic, weak) id<QiPageContentViewDelegate> contentViewDelgate;
復(fù)制代碼QiPageContentView和QiPageMenuView組合實(shí)現(xiàn)分頁界面QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) titles:@[@
"系統(tǒng)消息",@
"節(jié)日消息",@
"廣播通知",@
"最新",@
"最熱"] dataSource:dataSource];
menuView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:menuView];QiPageContentView *contenView = [[QiPageContentView alloc]initWithFrame:CGRectMake(0, menuView.bottom+10, self.view.width, self.view.height - menuView.bottom - 10 - 88-10) childViewController:@[ctrl,ctrl1,ctrl2,ctrl3,ctrl4]];
[self.view addSubview:contenView];menuView.pageItemClicked = ^(NSInteger clickedIndex, NSInteger beforeIndex, QiPageMenuView *menu) {NSLog(@
"點(diǎn)擊了:之前:%ld 現(xiàn)在:%ld",beforeIndex,clickedIndex);[contenView
setPageContentShouldScrollToIndex:clickedIndex beforIndex:beforeIndex];};contenView.pageContentViewDidScroll = ^(NSInteger currentIndex, NSInteger beforeIndex, QiPageContentView * _Nonnull pageView) {menuView.pageScrolledIndex = currentIndex;NSLog(@
"滾動(dòng)了:之前:%ld 現(xiàn)在:%ld",beforeIndex,currentIndex);};
復(fù)制代碼工程源碼GitHub地址
小編微信:可加并拉入《QiShare技術(shù)交流群》。
關(guān)注我們的途徑有:
QiShare(簡(jiǎn)書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公眾號(hào))
推薦文章:
iOS 中的界面旋轉(zhuǎn)
iOS 常用布局方式之Frame
iOS 常用布局方式之Autoresizing
iOS 常用布局方式之Constraint
iOS 常用布局方式之StackView
iOS 常用布局方式之Masonry
iOS UIButton根據(jù)內(nèi)容自動(dòng)布局
奇舞周刊
轉(zhuǎn)載于:https://juejin.im/post/5d0779595188251c9d45e9e9
總結(jié)
以上是生活随笔為你收集整理的iOS 快速实现分页界面的搭建的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。