Painted painted levels: fostered fostered fostered

Tags: “iOS” “pagination” “QiPageMenuView” author: Mu Ling Lo Review: QiShare team


IOS quickly realize the construction of paging interface

Scrolling pages are often used in projects to categorize the presentation of different data interfaces. We can preview the implementation first:

Implementation analysis

The implementation of this effect is divided into two parts: the top QiPageMenuView and the content display part QiPageContentView:

QiPageMenuView is based on UIScrollView. We can customize the effect we need to achieve according to our own project requirements. QiPageMenuView provides configurable properties including: whether each item of the menu adaptively widens according to the size of the text or sets a fixed width, the distance between the first and last items of the menu from the parent view, the distance between each item, including the display effect of each QiPageItem customization, etc. It also realizes the effect of automatically sliding menu items beyond one screen:

QiPageContentView is a wrapper based on the UIPageViewController implementation, and there may be several such interface effects in the project. Simply use UIPageViewController to write in the corresponding controller, add the corresponding child controller, by implementing the data source and proxy protocol of UIPageViewController can also achieve this effect. However, UIPageViewController is nested in the main controller, which has a high coupling degree and a large amount of code. If you need to use this effect in multiple places, you will write the UIPageViewController every time, which is not efficient and portable. QiPageMenuView and QiPageContentView are decoupled and can be used as separate controls. When designing, the menu view may look like a view other than the QiPageMenuView style. If the coupling is too high, it becomes a combination of QiPageContentView + QiPageMenuView, limiting the effect that can be presented.

QiPageMenuView implementation and use
  1. Qipagemenuview. h shows the QiPageMenuView can be customized related attributes and initialization method introduction.
@interface QiPageMenuView : UIScrollView<QiPageControllerDelegate> /** Menu bar clicked event */ @Property (nonatomic,copy)void(^pageItemClicked)(NSInteger) clickedIndex,QiPageMenuView *menu); /** Normal item font color */ @property (nonatomic,strong)UIColor *normalTitleColor; /** Select the font color of item */ @property (nonatomic,strong)UIColor *selectedTitleColor; */ @property (nonatomic,strong)UIFont *titleFont; /** Select Item font */ @property (nonatomic,strong)UIFont *selectedTitleFont; */ @property (nonatomic,assign)CGFloat itemTitlePadding; /** The distance between items. Itemisverticalalgrasped = NO when the space was set valid */ @Property (nonatomic,assign)CGFloat itemTopPadding; /** items left indent */ @property (nonatomic,assign)CGFloat leftMargin; /** items indent */ @property (nonatomic,assign)CGFloat rightMargin; @property (nonatomic,assign)BOOL itemsAutoResizing; /** whether the item is vertically centered, default yes; ItemTopPadding and lineTopPadding don't work; Setting NO itemHeight indicates the adaptive high */ @property (nonatomic,assign)BOOL itemIsVerticalCentred; /** Space between items */ @property (nonatomic,assign)CGFloat itemSpace; /** The height of each item */ @property (nonatomic,assign)CGFloat itemHeight; /** The width of each item. ItemsAutoResizing = YES No assignment is required. Otherwise the value must be given. */ @property (nonatomic,assign)CGFloat itemWidth; /** Whether to display underline default YES */ @property (nonatomic,assign)BOOL hasUnderLine; /** Underline color */ @property (nonatomic,strong)UIColor *lineColor; /** Spacing from underline to item */ @property (nonatomic,assign)CGFloat lineTopPadding; /** Underline height */ @property (nonatomic,assign)CGFloat lineHeight; /** The width of the underline */ @property (nonatomic,assign)CGFloat lineWitdh; /** pageController / / @property (nonatomic,assign)NSInteger pageScrolledIndex; /** initialization method */ - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles dataSource:(NSDictionary<QiPageMenuViewDataSourceKey, id> *)dataSource; - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles; /** slide to @param pageItem item */ - (void)scrollToPageItem:(QiPageItem*)pageItem; / *! @ @ brief update title array param items selectedIndex reset the selected item * / - (void) updateMenuViewWithNewItemArray (NSArray *) items selectedIndex:(NSInteger)selectedIndex; @endCopy the code
  1. QiPageMenuView slide display core code
- (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 = CGRectGetMinX(originalRect)+CGRectGetWidth(originalRect)/2; If (CGRectGetMidX(convertRect) < CGRectGetMidX(self.frame)) {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]; }}Copy the code
  1. QiPageMenuView uses two methods
  • A:
/ / custom style 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: @ @ "news," @ "festival news," @ "broadcast announcement," @ "QISHARE," @ "strange dance company"] dataSource: dataSource]; menuView.backgroundColor = [UIColor orangeColor]; [self.view addSubview:menuView];Copy the code
  • Method 2:
QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) Titles :@[@" System News ",@" Festival News ",@" Broadcast notification "]]; menuView.backgroundColor = [UIColor orangeColor]; / / custom style 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];Copy the code
QiPageContentView implementation and use
  1. QiPageContentView.h
@interface QiPageContentView : UIView<UIPageViewControllerDelegate, UIPageViewControllerDataSource,UIScrollViewDelegate> @property (nonatomic, strong) UIPageViewController *pageViewController; @property (nonatomic, strong) NSArray *controllerArray; / /! < controller array /** slide end: Block callback */ @Property (nonatomic,copy)void(^pageContentViewDidScroll)(NSInteger currentIndex,NSInteger beforeIndex,QiPageContentView *pageView); / * * end of the slide: agent callback If implementation block agent can't * / @ property (nonatomic, weak) id < QiPageContentViewDelegate > contentViewDelgate; / * * set the slide to a controller @ param index index @ param beforeIndex control direction * / - (void) setPageContentShouldScrollToIndex (NSInteger) index  beforIndex:(NSInteger)beforeIndex; @param frame frame @param childViewControllers @return instance */ - (instancetype)initWithFrame:(CGRect)frame childViewController:(NSArray*)childViewControllers; @endCopy the code
  1. QiPageContentView use
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];
Copy the code
QiPageContentView is decoupled from QiPageMenuView

QiPageContentView and QiPageMenuView use the protocol or block attribute defined in their headers to realize the event interaction between them, so as to achieve the pagination linkage effect. The decoupling of the two makes their use more flexible.

  1. QiPageMenuView Interaction event passing
@protocol QiPageMenuViewDelegate <NSObject> /** menu click on an item @param index click on index */ - (void)pageMenuViewDidClickedIndex:(NSInteger)index beforeIndex:(NSInteger)beforeIndex; @end @interface QiPageMenuView : / / @Property (nonatomic,copy)void(^pageItemClicked)(NSInteger clickedIndex,NSInteger beforeIndex,QiPageMenuView *menu); */ @property (nonatomic, weak) id<QiPageMenuViewDelegate> menuViewDelgate; */ @property (nonatomic, weak) id<QiPageMenuViewDelegate> menuViewDelgate;Copy the code
  1. QiPageContentView Interaction event delivery
@ protocol QiPageContentViewDelegate < NSObject > / * * sliding complete callback @ param index sliding to the 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; / /! < controller array /** slide end: Block callback */ @Property (nonatomic,copy)void(^pageContentViewDidScroll)(NSInteger currentIndex,NSInteger beforeIndex,QiPageContentView *pageView); / * * end of the slide: agent callback If implementation block agent can't * / @ property (nonatomic, weak) id < QiPageContentViewDelegate > contentViewDelgate;Copy the code
  1. QiPageContentView and QiPageMenuView are combined to realize paging interface
QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) titles: @ @ "system messages," @ "festival news," @ "broadcast announcement," @ "latest," @ "hottest"] 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(@" clicked: before: % ld now: % ld, "beforeIndex, clickedIndex); [contenView setPageContentShouldScrollToIndex:clickedIndex beforIndex:beforeIndex]; }; contenView.pageContentViewDidScroll = ^(NSInteger currentIndex, NSInteger beforeIndex, QiPageContentView * _Nonnull pageView) { menuView.pageScrolledIndex = currentIndex; Before the NSLog (@ "rolling: : % ld now: % ld", beforeIndex, currentIndex); };Copy the code

Project source GitHub address


Recommended articles:

Constraint iOS navigation: Frame iOS Autoresizing iOS navigation: Constraint iOS navigation: StackView iOS navigation: Constraint iOS navigation: Frame iOS UIButton automatically arranges odd dance weekly according to the content