程序员首页投稿(暂停使用,暂停投稿)iOS 技术文档收录

iOS:上下左右滑动布局的实现

2016-08-15  本文已影响4444人  琪一可
*效果图*.gif

需求: 实现一张列表, 左边的侧边栏固定,右边能够上下左右滑动, 能够点击某一行, 进入下一个界面,伴随有点击的高亮效果。

如果没有点击的效果, 那我们很容易会联想到的是collectionView,通过重写他的UICollectionViewLayout中的- (void)prepareLayout等方法来实现。而今天我实现这种布局的方法用的是两个tableView, 一个scrollView。scrollView可以上下左右滑动,能够实现右侧的左右滑动的效果;tableView则能够实现页面的布局。

1.布局

首先在左侧铺建了一个tableView, 这个tableView的头视图就是上面gif图中的‘统计’。而右侧的tableView首先是添加在scrollView上面的。这个scrollView的宽度由有多少列决定的。tableView 的宽度和scrollView的宽度相同, 高度相同。tableView的头视图就是gif图里面, ‘A级, B级’的那个。这里的tableView都是采用的UITableViewStylePlain。

2.关联tableView的上下左右滑动

设置scrollView的滑动方向是水平的,所以tableView看上去就能够左右滑动了, 这也是为什么tableView的宽度和scrollView的宽度一致。 而竖直方向上面的滑动逻辑, 就让tableView去处理。
tableView继承于UIScrollView,所以这两个tableView都能在滑动的时候触发的方法有- (void)scrollViewDidScroll:(UIScrollView *)scrollView,目的是为了在左侧的tableView上下滑动的时候,右侧跟随滑动; 右侧的tableView滑动的时候, 左侧的跟随滑动。 在这个方法里面实现关联的逻辑:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (scrollView == self.rightTableView) {
        if (self.leftTableView.contentOffset.y != self.rightTableView.contentOffset.y) {
            self.leftTableView.contentOffset = CGPointMake(0, self.rightTableView.contentOffset.y);
        }
    } else if (scrollView == self.leftTableView) {
        if (self.rightTableView.contentOffset.y != self.leftTableView.contentOffset.y) {
            self.rightTableView.contentOffset = CGPointMake(self.rightTableView.contentOffset.x, self.leftTableView.contentOffset.y);
        }
    }
}

3.点击效果

点击的时候, 两个tableView的效果要同时出现,而didSelectRowAtIndexPath方法是自动调用的,为了实现平时的那种点击tableView时候的deselectRowAtIndexPath的效果,能够联想到了didHighlightRowAtIndexPathdidUnhighlightRowAtIndexPath方法。于是可以用这三个方法实现行高亮,代码如下:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView == _leftTableView || tableView == _rightTableView) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self changeTableViewCellBackgroundColor:NO indexPath:indexPath];
        });
    }
}

- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView == _leftTableView || tableView == _rightTableView) {
        [self changeTableViewCellBackgroundColor:YES indexPath:indexPath];
    }
}

- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView == _leftTableView || tableView == _rightTableView) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self changeTableViewCellBackgroundColor:NO indexPath:indexPath];
        });
        [self didSelectTableViewCell:tableView indexPath:indexPath];
    }
}

/// cell点击事件
- (void)didSelectTableViewCell:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath
{
    
}

- (void)changeTableViewCellBackgroundColor:(BOOL)change indexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell1 = [_leftTableView cellForRowAtIndexPath:indexPath];
    UITableViewCell *cell2 = [_rightTableView cellForRowAtIndexPath:indexPath];
    if (change) {
        cell1.backgroundColor = SelectColor;
        cell2.backgroundColor = SelectColor;
    } else {
        [UIView animateWithDuration:.2 animations:^{
            cell1.backgroundColor = ColorWhite;
            cell2.backgroundColor = ColorWhite;
        }];
    }
}

注意:tableViewCell要设置:

cell.selectionStyle = UITableViewCellSelectionStyleNone;

4.右侧的tableViewCell里面的布局

需要按照返回数据提供的列数来创建label。于是,在传值的方法里面, 创建label; 如果label已经存在, 就不再创建,直接赋值。
示例代码如下:

- (void)configureWithItem:(id)item
{
    NSArray *datas = item;
    CGFloat widthForItem = 100;
    CGFloat heightForItem = 50;
    UILabel *label = [self viewWithTag:100];
    
    if (label == NULL) {
        
        for (NSInteger i = 0 ; i < datas.count; i++) {
            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(widthForItem * i, 0, widthForItem, heightForItem - 3)];
            
            label.textAlignment = NSTextAlignmentCenter;
            label.numberOfLines = 2;
            label.text = datas[i];
            label.tag = 100 + i;
            [self addSubview:label];
            
        }
        UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,  heightForItem - .5,  widthForItem * datas.count, .5)];
        lineView.backgroundColor = ColorTableSeparator;
        [self.contentView addSubview:lineView];
        
    } else {
        for (int i = 0; i < datas.count; i++) {
            UILabel *label = [self viewWithTag:100 + i];
            label.text = datas[i];
        }
    }
}

Demo地址

本文提供的是一种思路, 如果有更好的思路, 希望能够在评论区提出来, 共同进步。 谢谢。

上一篇 下一篇

猜你喜欢

热点阅读