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

作者: 琪一可 | 来源:发表于2016-08-15 10:49 被阅读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地址

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

    相关文章

      网友评论

        本文标题:iOS:上下左右滑动布局的实现

        本文链接:https://www.haomeiwen.com/subject/iocesttx.html