首页 > 学院 > 开发设计 > 正文

iOS菜单滚动联动内容区域功能实现

2019-11-14 18:08:23
字体:
来源:转载
供稿:网友

平时开发APP中关于此功能还是比较经常碰到,本实例借用三个开源的插件,并对其中一个进行修改调整实现出想要的效果;本文重点介绍修改的内容跟三个插件的运用,这三个插件还可以各自扩展到其它项目的运用;

效果图:

 

本实例实现的效果:顶部的滚动菜单显示出所有的类型,每个类型都对应一种展示,可以在顶部的菜单进行滚动,内容区域也会跟着改变,或者是内容区域左右滑动,则顶部的滚动菜单也会跟着更改,顶部菜单的最右边有一个展示更多菜单的效果,用于弹出一个带箭头的窗;(源代码下载)

 带箭头的弹出视图插件 :https://github.com/xiekw2010/DXPopover

 内容区域滑动插件:https://github.com/nicklockwood/iCarousel

 及Codint.Net开源项目中的XTSegmentControl菜单滚动效果,此实例对它进行的修改

1:插件及页面的初始化

#import "ViewController.h"#import "oldChildVewController.h"#import "ChildViewController.h"#import "newChildVewController.h"#import "XTSegmentControl.h"#import "iCarousel.h"#import "Masonry.h"#import "menuCollectionViewCell.h"#import "DXPopover.h"#define kScreen_Height [UIScreen mainScreen].bounds.size.height#define kScreen_Width [UIScreen mainScreen].bounds.size.width#define kMySegmentControl_Height 44.0@interface ViewController ()<UICollectionViewDataSource, UICollectionViewDelegate,iCarouselDataSource, iCarouselDelegate>@PRoperty (strong, nonatomic) XTSegmentControl *mySegmentControl;@property (strong, nonatomic) NSArray *titlesArray;@property (strong, nonatomic) iCarousel *myCarousel;@property(assign,nonatomic)NSInteger curSelectIndex;@property (nonatomic, strong) DXPopover *popover;@property(assign,nonatomic)CGFloat popoverWidth;@property (strong, nonatomic) UICollectionView *myCollectionView;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];        self.view.backgroundColor=[UIColor whiteColor];        //初始化一个popover 用于弹窗效果的展示    self.popover = [DXPopover new];    _popoverWidth = kScreen_Width-20;        __weak typeof(self) weakSelf = self;    CGRect frame=self.view.bounds;        //内容区滚动效果插件    self.myCarousel = ({        iCarousel *icarousel = [[iCarousel alloc] initWithFrame:frame];        icarousel.dataSource = self;        icarousel.delegate = self;        icarousel.decelerationRate = 1.0;        icarousel.scrollSpeed = 1.0;        icarousel.type = iCarouselTypeLinear;        icarousel.pagingEnabled = YES;        icarousel.clipsToBounds = YES;        icarousel.bounceDistance = 0.2;        [self.view addSubview:icarousel];        [icarousel mas_makeConstraints:^(MASConstraintMaker *make) {            make.edges.equalTo(self.view).insets(UIEdgeInsetsMake(64, 0, 0, 0));        }];        icarousel;    });        //添加滑块    __weak typeof(_myCarousel) weakCarousel = _myCarousel;    self.mySegmentControl = [[XTSegmentControl alloc] initWithFrame:CGRectMake(0, 20, kScreen_Width, 44) Items:self.titlesArray showRightButton:YES selectedBlock:^(NSInteger index) {        weakSelf.curSelectIndex=index;        weakCarousel.currentItemIndex=index;        [weakSelf.myCollectionView reloadData];    }];    //当有右边键时 其响应的事件    self.mySegmentControl.rightButtonBlock= ^(CGRect rightButtomRect)    {        //弹出插件的运用        [weakSelf updateMyViewFrame];        CGPoint startPoint =        CGPointMake(CGRectGetMidX(rightButtomRect), CGRectGetMaxY(rightButtomRect) + 25);        [weakSelf.popover showAtPoint:startPoint                   popoverPostion:DXPopoverPositionDown                  withContentView:weakSelf.myCollectionView                           inView:weakSelf.view];    };    [self.view addSubview:self.mySegmentControl];        //用于展示弹出效果里面的列表    if (!_myCollectionView) {        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];        self.myCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,50,kScreen_Width-40, 200) collectionViewLayout:layout];        self.myCollectionView.backgroundColor=[UIColor whiteColor];        self.myCollectionView.showsHorizontalScrollIndicator=NO;        self.myCollectionView.showsVerticalScrollIndicator=NO;        [self.myCollectionView registerClass:[menuCollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([menuCollectionViewCell class])];        self.myCollectionView.dataSource = self;        self.myCollectionView.delegate = self;    }}

其中XTSegmentControl为顶部菜单的创建,其中showRightButton是为了扩展是否显示右边更多菜单的事件,并把事件的响应Block到页面进行实现,此事例就是响应弹出窗的效果展现iCarousel为内容区域的滑动效果,DXPopover弹出窗的效果,UICollectionView则用于弹出窗里面的菜单列表

//popver一些属性的设置-(void)updateMyViewFrame{    CGRect tableViewFrame = self.myCollectionView.frame;    tableViewFrame.size.width = _popoverWidth;    self.myCollectionView.frame = tableViewFrame;    self.popover.contentInset = UIEdgeInsetsZero;    self.popover.backgroundColor = [UIColor whiteColor];}#pragma mark - Getter/Setter- (NSArray*)titlesArray{    if (nil == _titlesArray) {            _titlesArray = @[@"全部", @"互动", @"开源控件", @"文档", @"代码", @"高尔夫",@"主题",@"软件",@"股票"];    }    return _titlesArray;}

2插件iCarouselDataSource, iCarouselDelegate代码实现

#pragma mark iCarousel M- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel{    return [self.titlesArray count];}//滚动时内容视图的加载- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view{    [_mySegmentControl setScrollOffset:index];    UIViewController *childContrll=[[ChildViewController alloc]init];    UIView *my=childContrll.view;    switch (index) {        case 0:        {            my.backgroundColor=[UIColor blackColor];            break;        }        case 1:        {            my.backgroundColor=[UIColor redColor];            break;        }        default:            childContrll=[[newChildVewController alloc]init];            break;    }    return childContrll.view;}//滚动时 下划线的位置更新- (void)carouselDidScroll:(iCarousel *)carousel{    if (_mySegmentControl) {        [_mySegmentControl moveIndexWithProgress];    }}//更新滚动其它两个控件的位置- (void)carouselCurrentItemIndexDidChange:(iCarousel *)carousel{    self.curSelectIndex=carousel.currentItemIndex;    [self.myCollectionView reloadData];    if (_mySegmentControl) {        _mySegmentControl.currentIndex = carousel.currentItemIndex;    }}

注意:内容区域的视图加载,及其滑动所响应的事件处理,原来的XTSegmentControl对于菜单字数不同时下划线会出现一些异常,本实例对它进行修改了;

3:列表UICollectionViewDataSource, UICollectionViewDelegate功能的实现

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{    return self.titlesArray.count;}- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    menuCollectionViewCell *ccell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([menuCollectionViewCell class]) forIndexPath:indexPath];    NSString *model=[self.titlesArray objectAtIndex:indexPath.row];    ccell.curMenuModel=model;    if (self.curSelectIndex==indexPath.row) {        ccell.backgroundColor=[UIColor blueColor];    }    else    {        ccell.backgroundColor=[UIColor whiteColor];    }    return ccell;}- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{    return CGSizeMake((kScreen_Width-40)/3, 40);}- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{    return UIEdgeInsetsZero;}- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{    return 5;}- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{    return 5;}- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{    self.curSelectIndex=indexPath.row;    //两个滚动的位置更新    _myCarousel.currentItemIndex=self.curSelectIndex;    [_mySegmentControl selectIndex:self.curSelectIndex];    //隐藏弹出窗    [self.popover dismiss];}

注意:主要是在实现点击时滚动位置跟内容的区域要进行调整,并把弹出窗进行收缩的操作;

4:XTSegmentControl下划线调整

- (void)moveIndexWithProgress{    CGRect origionRect = [_itemFrames[_currentIndex] CGRectValue];        CGRect origionLineRect = CGRectMake(CGRectGetMinX(origionRect) + XTSegmentControlHspace, CGRectGetHeight(origionRect) - XTSegmentControlLineHeight, CGRectGetWidth(origionRect) - 2 * XTSegmentControlHspace, XTSegmentControlLineHeight);        //增加下划线滚动的效果    [UIView animateWithDuration:0.5 animations:^{        _lineView.frame = origionLineRect;    } completion:^(BOOL finished) {            }];    }

5:扩展XTSegmentControl没有右边更多菜单的效果

    self.mySegmentControl = [[XTSegmentControl alloc] initWithFrame:CGRectMake(0, 20, kScreen_Width, 44) Items:self.titlesArray showRightButton:NO selectedBlock:^(NSInteger index) {        weakSelf.curSelectIndex=index;        weakCarousel.currentItemIndex=index;        [weakSelf.myCollectionView reloadData];    }];

效果图:

 

6:补充关于popover这个插件的如果有模态时,它会出现整个屏幕,如果不想要这种效果,可以自个设置一个背景视图效果,把popover模态效果关掉(self.popover.maskType=DXPopoverMaskTypeNone; //设置默认是否有模态);下面是写的一个实例:

 

- (void)updateTableViewFrame {    CGRect tableViewFrame = self.tableView.frame;    tableViewFrame.size.width = _popoverWidth;    self.tableView.frame = tableViewFrame;    self.popover.contentInset = UIEdgeInsetsZero;    self.popover.maskType=DXPopoverMaskTypeNone; //设置默认是否有模态    self.popover.backgroundColor = [UIColor whiteColor];}- (void)showPopover {    [self updateTableViewFrame];    [self changeShowing];        CGPoint startPoint =        CGPointMake(CGRectGetMidX(self.btn.frame), CGRectGetMaxY(self.btn.frame) + 5);    [self.popover showAtPoint:startPoint               popoverPostion:DXPopoverPositionDown              withContentView:self.tableView                       inView:self.tabBarController.view];    __weak typeof(self) weakSelf = self;    self.popover.didDismissHandler = ^{        [weakSelf bounceTargetView:weakSelf.btn];    };}//自行增加一个背影层- (UIView *)myTapBackgroundView{    if (!_myTapBackgroundView) {        _myTapBackgroundView = ({            UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 64, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height-64)];            view.backgroundColor = [UIColor clearColor];            UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeShowing)];            [view addGestureRecognizer:tap];            view;        });    }    return _myTapBackgroundView;}- (void)changeShowing{    if (self.isShowing) {//隐藏        [UIView animateWithDuration:0.3 animations:^{            self.myTapBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0];        } completion:^(BOOL finished) {            [self.popover dismiss];            [self.myTapBackgroundView removeFromSuperview];            self.isShowing = NO;        }];    }else{//显示        [self.view addSubview:self.myTapBackgroundView];        [UIView animateWithDuration:0.3 animations:^{            self.myTapBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];        } completion:^(BOOL finished) {            self.isShowing = YES;        }];    }}

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表