iOS菜單滾動聯動內容區域功能實現

平時開發APP中關於此功能仍是比較常常碰到,本實例借用三個開源的插件,並對其中一個進行修改調整實現出想要的效果;本文重點介紹修改的內容跟三個插件的運用,這三個插件還能夠各自擴展到其它項目的運用;git

效果圖:github

 

本實例實現的效果:頂部的滾動菜單顯示出全部的類型,每一個類型都對應一種展現,能夠在頂部的菜單進行滾動,內容區域也會跟着改變,或者是內容區域左右滑動,則頂部的滾動菜單也會跟着更改,頂部菜單的最右邊有一個展現更多菜單的效果,用於彈出一個帶箭頭的窗;(源代碼下載)atom

 帶箭頭的彈出視圖插件 :https://github.com/xiekw2010/DXPopoverspa

 內容區域滑動插件:https://github.com/nicklockwood/iCarousel.net

 及Codint.Net開源項目中的XTSegmentControl菜單滾動效果,此實例對它進行的修改插件

1:插件及頁面的初始化code

#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則用於彈出窗裏面的菜單列表blog

//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對於菜單字數不一樣時下劃線會出現一些異常,本實例對它進行修改了;ip

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;
        }];
    }
}
相關文章
相關標籤/搜索