iOS scrollView中嵌套多個tableView處理方案


項目中經常會有這樣的需求,scrollView有個頭部,當scrollView滾動的時候頭部也跟着滾動,同時頭部還有一個tab會鎖定在某個位置,scrollView中可以放很多不同的view,這些view可以在scrollView中橫向滾動,要實現這樣的需求,按理說如果頭部是固定不動的,那么在scrollView嵌套多層view,同時控制這些view的在scrollView中的位置,是很好實現的,這里的難點在scrollView的頭部也是可以滾動的。
解決以上問題有2中方法可以考慮
方法1:
不用scrollView,直接用一個tableView,頭部作為tableView的tableHeaderView。當頭部的tab被點擊了,切換tableView的數據源,通過一個index來標識當前選中了那個tab,然后讓tableView去刷新指定的數據源。如果你用這種方法好處是很快就可以實現功能,我想遇到這樣的需求,大部分人都是采用的這種方案吧。缺點了也是很明顯,所有tab公用一個tableView,就會導致tableView中的業務相當復雜,tableView中的代碼會非常多,並且可拓展性也不強。
方法2:
用scrollView,讓scrollView覆蓋其父視圖的整個界面,然后創建多個view作為scrollView的子視圖,這里的view不限定是tableView,collectionView也是可以的,把創建的n個View依次添加到scrollView中,注意這些view的x軸,同時設置scrollview的contentsize,我們再創建一個headerView,作為scrollView的頭部。同時通過addSubview的方式把headerView添加到scrollView中,注意要保證headerView要在最上層,防止其被遮住。每個tableView在被創建的時候提供一個setHeader的方法,並且傳入這個創建headerView,在setheader方法中,我們拿到headerView的真實寬高,並為該tableView添加一個相同高度的tableHeaderView,其實大概意思就是為所有tableView都添加一個和scrollView的headview大小相同的tableViewHeaderView,由於我們的scrollView的header浮在最上層,剛好完美的遮住這些tableView的tableHeaderView,當我們tableView上下滑動的時候控制headerView和tableView的tableHeaderView同步滑動就可以了,當我們需要橫向滑動的時候,監聽scrollView的contentoffset,讓headrView的x軸跟隨scrollView滑動,這樣聯動就算完成了。剩下的就是處理點擊事件,處理滑動事件的問題了。說了這么多,估計都有點糊塗了把,還是直接上代碼把,這里把部分核心代碼帖處理,並且在文章結束的時候送上測試demo

#import "ViewController.h"
#import "UIView+XYView.h"
#import "TYTableView1.h"
#import "TableView2.h"
#import "TYHeaderView.h"

#define kHeadHeight    300

@interface ViewController ()<UIScrollViewDelegate,headerViewDelegate>

@property (nonatomic, strong) UIScrollView *scrollView;

@property (nonatomic, strong) TYHeaderView *headerView;

@property (nonatomic, strong) TYTableView1 *tableView1;

@property (nonatomic, strong) TableView2 *tableView2;

@property (nonatomic, assign) CGPoint lastContentOffset;



@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    [self setupUI];
    
}


-(TYHeaderView *)headerView{
    if (!_headerView) {
        _headerView = [[TYHeaderView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, kHeadHeight)];
        _headerView.backgroundColor = [UIColor redColor];
        _headerView.delegate = self;
    }
    return _headerView;
}

-(UIScrollView *)scrollView{
    if (!_scrollView) {
        _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        _scrollView.delegate = self;
        _scrollView.pagingEnabled = YES;
        _scrollView.showsVerticalScrollIndicator = NO;
        _scrollView.showsHorizontalScrollIndicator = NO;
        _scrollView.contentSize = CGSizeMake(SCREEN_WIDTH *2, 0);
    }
    return _scrollView;
}

-(UITableView *)tableView1{
    if (!_tableView1) {
        _tableView1 = [[TYTableView1 alloc] initWithFrame:CGRectMake(0, 0,SCREEN_WIDTH, self.scrollView.height)];
        _tableView1.showsHorizontalScrollIndicator = NO;
        _tableView1.showsVerticalScrollIndicator = NO;
        _tableView1.headerView = self.headerView;
    }
    return _tableView1;
}

-(UITableView *)tableView2{
    if (!_tableView2) {
        _tableView2 = [[TableView2 alloc] initWithFrame:CGRectMake(SCREEN_WIDTH, 0,SCREEN_WIDTH, self.scrollView.height)];
        _tableView2.showsHorizontalScrollIndicator = NO;
        _tableView2.showsVerticalScrollIndicator = NO;
        _tableView2.headerView = self.headerView;
    }
    return _tableView2;
}

-(void)setupUI{
    [self.view addSubview:self.scrollView];
    [self.scrollView addSubview:self.tableView1];
    [self.scrollView addSubview:self.tableView2];
    [self.scrollView addSubview:self.headerView];
    
}

#pragma mark - ScrollViewDelegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if (scrollView == self.scrollView) {
        self.headerView.x = scrollView.contentOffset.x;
        int index = 0;
        
        if (self.lastContentOffset.x < scrollView.contentOffset.x) {
            //往右滑動,向上取整
            index = ceil((scrollView.contentOffset.x/SCREEN_WIDTH));
        }else if (self.lastContentOffset.x > scrollView.contentOffset.x)
        {
            //往左滑動,向下取整
            index = floor((scrollView.contentOffset.x/SCREEN_WIDTH));
        }else
        {
            //沒動
            index = (scrollView.contentOffset.x/SCREEN_WIDTH);
        }
        
        CGFloat mobileDistance = (0-self.headerView.y);
        switch (index) {
            case 0:{
                //修改circleTableView
                if (self.tableView1.contentOffset.y<mobileDistance) {
                    [self.tableView1 setContentOffset:CGPointMake(0, mobileDistance) animated:NO];
                }
            }
                break;
            case 1:{
                //修改photoView
                if (self.tableView2.contentOffset.y<mobileDistance) {
                    [self.tableView2 setContentOffset:CGPointMake(0, mobileDistance) animated:NO];
                }
            }
                break;
            default:
                break;

        }
        self.lastContentOffset = scrollView.contentOffset;
    }
}

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    static int lastIndex = 0;
    int index = 0;

    if (self.lastContentOffset.x < scrollView.contentOffset.x) {
        //往右滑動,向上取整
        index = ceil((scrollView.contentOffset.x/SCREEN_WIDTH));
    }else if (self.lastContentOffset.x > scrollView.contentOffset.x)
    {
        //往左滑動,向下取整
        index = floor((scrollView.contentOffset.x/SCREEN_WIDTH));
    }else
    {
        //沒動
        index = (scrollView.contentOffset.x/SCREEN_WIDTH);
    }
//    if (lastIndex != index) {  //讓headerView重新設置選中的item
        self.headerView.selectIndex = index;
//    }
    lastIndex = index;
}

#pragma mark - headerViewDelegate
-(void)headerView:(TYHeaderView *)headerView SelectionIndex:(NSInteger)index{
    //讓scrollView滾動到指定位置
    [self.scrollView setContentOffset:CGPointMake(self.scrollView.width*index, 0) animated:YES];
}

上面這段代碼主要就怎么給scrollView添加子視圖 如果設置子視圖的位置和headerView的位置

#import "TYTableView1.h"

@interface TYTableView1 ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, assign) CGPoint lastContentOffset;

@end

@implementation TYTableView1

-(void)setHeaderView:(TYHeaderView *)headerView{
    _headerView = headerView;
    self.dataSource = self;
    self.delegate = self;
    self.scrollIndicatorInsets = UIEdgeInsetsMake(headerView.height, 0, 0, 0);
    UIView *tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, self.headerView.height)];
    self.tableHeaderView = tableHeaderView;
    [self reloadData];
}

#pragma mark - ScrollViewDelegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat placeHolderHeight = self.headerView.height - 44;
    CGFloat offsetY = scrollView.contentOffset.y;
    if (offsetY >= 0 && offsetY <= placeHolderHeight) {
        if (offsetY > self.lastContentOffset.y) {
            //往上滑動
            if (offsetY>(-self.headerView.y)) {
                self.headerView.y = -offsetY;
            }
        }else
        {
            //往下滑動
            if (offsetY<(-self.headerView.y)) {
                self.headerView.y = -offsetY;
            }
        }
    }
    else if (offsetY > placeHolderHeight) {
        if (self.headerView.y != (-placeHolderHeight)) {
            if (offsetY > self.lastContentOffset.y) {
                //往上滑動
                self.headerView.y = self.headerView.y - (scrollView.contentOffset.y-self.lastContentOffset.y);
            }
            if (self.headerView.y < (-placeHolderHeight)) {
                self.headerView.y = -placeHolderHeight;
            }
            if (self.headerView.y>=0) {
                self.headerView.y = 0;
            }
        }
    }
    else if (offsetY <0) {
        self.headerView.y =  - offsetY;
    }
    
//    if (offsetY>50) {
//        self.headerView.navView.transparency = 1;
//    }else
//    {
//        self.headerView.navView.transparency = 0;
//    }
    
    self.lastContentOffset = scrollView.contentOffset;
}

#pragma mark - UITableViewDelegate && UITableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 20;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.textLabel.text = @"測試數據";
    return cell;
}

這一段主要是目的就是如果setHederView,並且設置一個同header同樣寬高的tableViewHeaderView,並且監聽tableView的滾動,保證headerView的滾動和tableHeaderView同步,第一個tableView的設置是這樣的,第二個,第三個tableView的設置也是一樣的,這里就不在多說了,這里還有一個注意點,就是當header滾動要一定程度了之后需要控制headerView的最大滾動區域,這樣才可以保障tab始終懸浮在tableView的最頂部。

整體的實現思路和相關代碼都已經貼出來,多的我也就不廢話了,
demo的下載地址 https://github.com/qqcc1388/xmDemo

轉載請標注來源 http://www.cnblogs.com/qqcc1388/p/8662375.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM