iOS 快速实现分页界面的搭建

栏目: IOS · 发布时间: 7年前

内容简介:项目中我们经常会遇到滚动分页的设计效果,被用来对不同数据界面的展示进行分类。我们先可以来预览一下实现效果:根据动图进行实现分析:这个效果的实现分为两部分顶部的QiPageMenuView和内容展示部分QiPageContentView:QiPageMenuView是基于UIScrollView实现的,我们可以按照自己的项目需求,定制自己需要实现的效果。QiPageMenuView提供了可设置的属性有:菜单每一项是否根据文字的大小自适应宽度还是设置固定宽度、菜单的首项和最后一项距离父视图的间距、每一项之间的间

项目中我们经常会遇到滚动分页的设计效果,被用来对不同数据界面的展示进行分类。我们先可以来预览一下实现效果:

iOS 快速实现分页界面的搭建

实现分析

根据动图进行实现分析:这个效果的实现分为两部分顶部的QiPageMenuView和内容展示部分QiPageContentView:

QiPageMenuView是基于UIScrollView实现的,我们可以按照自己的项目需求,定制自己需要实现的效果。QiPageMenuView提供了可设置的属性有:菜单每一项是否根据文字的大小自适应宽度还是设置固定宽度、菜单的首项和最后一项距离父视图的间距、每一项之间的间距、包括了每一项QiPageItem的展示效果自定义等。也实现了菜单项超出一屏幕时自动滑动显示的效果:

iOS 快速实现分页界面的搭建

QiPageContentView是基于UIPageViewController实现的封装,在项目中可能有多处这样的界面效果。单纯的使用UIPageViewController写在相应的控制器中,添加相应的子控制器,通过实现UIPageViewController的数据源和代理协议也可以达到这种效果。但是UIPageViewController嵌套在主控制器中,耦合度比较高,代码量也比较大,若是多处需要使用这种效果,每次都写一遍UIPageViewController,效率和可移植性不高。 QiPageMenuView和QiPageContentView之间是解耦合的,彼此都可以作为单独的控件去使用。在设计构思时,菜单视图的样式有可能是QiPageMenuView样式之外的视图,若是两者耦合度太高,就变成了QiPageContentView + QiPageMenuView组合,能展现的效果就被限制了。

QiPageMenuView实现与使用

  1. QiPageMenuView.h中展现了QiPageMenuView可实现定制的相关属性以及初始化方法介绍。
@interface QiPageMenuView : UIScrollView<QiPageControllerDelegate>
/**
 菜单栏点击事件
 */
@property (nonatomic,copy)void(^pageItemClicked)(NSInteger clickedIndex,QiPageMenuView *menu);
/**
 常态item的字体颜色
 */
@property (nonatomic,strong)UIColor *normalTitleColor;
/**
 选中item的字体颜色
 */
@property (nonatomic,strong)UIColor *selectedTitleColor;
/**
 常态item的字体
 */
@property (nonatomic,strong)UIFont *titleFont;
/**
 选中Item的字体
 */
@property (nonatomic,strong)UIFont *selectedTitleFont;
/**
 字体距离item两边的间距,itemsAutoResizing = YES时 设置有效
 */
@property (nonatomic,assign)CGFloat itemTitlePadding;
/**
 item距上的间距。itemIsVerticalCentred = NO的时候设置有效
 */
@property (nonatomic,assign)CGFloat itemTopPadding;
/**
 items的左边缩进
 */
@property (nonatomic,assign)CGFloat leftMargin;
/**
 items的右边缩进
 */
@property (nonatomic,assign)CGFloat rightMargin;
/**
 是否根据文字的长度自动计算item的width default YES
 */
@property (nonatomic,assign)BOOL itemsAutoResizing;
/**
 item是否垂直居中显示,默认yes;  itemTopPadding 与 lineTopPadding 不会生效;设置NO itemHeight会自适应高
 */
@property (nonatomic,assign)BOOL itemIsVerticalCentred;
/**
 item之间的间距
 */
@property (nonatomic,assign)CGFloat itemSpace;
/**
 每个item的高度
 */
@property (nonatomic,assign)CGFloat itemHeight;
/**
 每个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滑动完成
 */
@property (nonatomic,assign)NSInteger pageScrolledIndex;
/**
 初始化方法
 */
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles dataSource:(NSDictionary<QiPageMenuViewDataSourceKey, id> *)dataSource;
- (instancetype)initWithFrame:(CGRect)frame titles:(NSArray*)titles;
/**
 滑动到某一项 
 @param pageItem item
 */
- (void)scrollToPageItem:(QiPageItem*)pageItem;
/*!
 @brief 更新标题数组
 @param items selectedIndex重置选中的item
 */
- (void)updateMenuViewWithNewItemArray:(NSArray *)items selectedIndex:(NSInteger)selectedIndex;
@end

复制代码
  1. QiPageMenuView滑动显示的核心代码
- (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)) {
        //是否需要右滑
        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];
    }
}
复制代码
  1. 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:@[@"消息",@"节日消息",@"广播通知",@"QISHARE",@"奇舞团"] dataSource:dataSource];
    menuView.backgroundColor = [UIColor orangeColor];
    [self.view addSubview:menuView];
复制代码
  • 方式二:
QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) titles:@[@"系统消息",@"节日消息",@"广播通知"]];
    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];
复制代码

QiPageContentView实现与使用

  1. QiPageContentView.h
@interface QiPageContentView : UIView<UIPageViewControllerDelegate, UIPageViewControllerDataSource,UIScrollViewDelegate>

@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *controllerArray; //!< 控制器数组
/**
 滑动结束:block回调
 */
@property (nonatomic,copy)void(^pageContentViewDidScroll)(NSInteger currentIndex,NSInteger beforeIndex,QiPageContentView *pageView);

/**
 滑动结束:代理回调 若实现block代理不会走
 */
@property (nonatomic, weak) id<QiPageContentViewDelegate> contentViewDelgate;

/**
 设置滑动至某一个控制器

 @param index index
 @param beforeIndex 控制方向
 */
- (void)setPageContentShouldScrollToIndex:(NSInteger)index beforIndex:(NSInteger)beforeIndex;

/**
 初始化方法

 @param frame frame
 @param childViewControllers childViewControllers
 @return 实例
 */
- (instancetype)initWithFrame:(CGRect)frame childViewController:(NSArray*)childViewControllers;

@end
复制代码
  1. 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];
复制代码

QiPageContentView与QiPageMenuView解耦

QiPageContentView与QiPageMenuView使用各自头文件中定义的协议或者block属性实现两者之间事件交互,从而达到分页联动效果;两者的解耦,使得它们的使用更加灵活。

  1. QiPageMenuView交互事件的传递
@protocol QiPageMenuViewDelegate <NSObject>
/**
 菜单点击了某个item
 
 @param index 点击了index
 */
- (void)pageMenuViewDidClickedIndex:(NSInteger)index beforeIndex:(NSInteger)beforeIndex;

@end

@interface QiPageMenuView : UIScrollView
/**
 菜单栏点击事件:block回调
 */
@property (nonatomic,copy)void(^pageItemClicked)(NSInteger clickedIndex,NSInteger beforeIndex,QiPageMenuView *menu);

/**
 菜单栏点击事件:代理回调 若实现block代理不会走
 */
@property (nonatomic, weak) id<QiPageMenuViewDelegate> menuViewDelgate;
复制代码
  1. QiPageContentView交互事件的传递
@protocol QiPageContentViewDelegate <NSObject>

/**
 滑动完成回调
 @param index 滑动至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; //!< 控制器数组
/**
 滑动结束:block回调
 */
@property (nonatomic,copy)void(^pageContentViewDidScroll)(NSInteger currentIndex,NSInteger beforeIndex,QiPageContentView *pageView);
/**
 滑动结束:代理回调 若实现block代理不会走
 */
@property (nonatomic, weak) id<QiPageContentViewDelegate> contentViewDelgate;

复制代码
  1. QiPageContentView和QiPageMenuView组合实现分页界面
QiPageMenuView *menuView = [[QiPageMenuView alloc]initWithFrame:CGRectMake(0, 0, self.view.width, 50) titles:@[@"系统消息",@"节日消息",@"广播通知",@"最新",@"最热"] 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(@"点击了:之前:%ld 现在:%ld",beforeIndex,clickedIndex);
   [contenView setPageContentShouldScrollToIndex:clickedIndex beforIndex:beforeIndex];
 };
    
contenView.pageContentViewDidScroll = ^(NSInteger currentIndex, NSInteger beforeIndex, QiPageContentView * _Nonnull pageView) {
   menuView.pageScrolledIndex = currentIndex;
   NSLog(@"滚动了:之前:%ld 现在:%ld",beforeIndex,currentIndex);
 };
复制代码

工程源码GitHub地址

小编微信:可加并拉入《QiShare技术交流群》。

iOS 快速实现分页界面的搭建

关注我们的途径有:

QiShare(简书)

QiShare(掘金)

QiShare(知乎)

QiShare(GitHub)

QiShare(CocoaChina)

QiShare(StackOverflow)

QiShare(微信公众号)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

Is Parallel Programming Hard, And, If So, What Can You Do About

Is Parallel Programming Hard, And, If So, What Can You Do About

Paul E. McKenney

The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具