UITableView 視差效果

yuud2866 7年前發布 | 11K 次閱讀 iOS開發 移動開發 UITableView

之前在項目中用過一個視差效果,其實實現并不是很難,我們先看一下效果

視差效果.gif

大概說一下思路:

每個cell中有一個UIImageView,在tableview向上滑動的時候,cell中的imageview相對cell向下移動,形成一個視差效果。也就是說,除了屏幕最上端的cell中的imageview的y為0以外,下面的cell中的imageview的Y值均為負值。

接下來就依照已知量來計算每個imageView的y值,并且在tableview滾動的時候實時更改imageView的Y值。

已知量:

  1. tableView的高度(tableViewHeight)
  2. tableView的偏移量
  3. cell的高度
  4. imageView的高度
  5. cell的Y值
  6. cell相主屏幕的偏移量(cellOffset) -> cellY值 - tableView的偏移量

求imageView的偏移量(imageViewOffset)。如下圖所示。

圖解.png

思路:

當cell的偏移量變為0的時候,imageViewY的值也由負值變為0。

imageViewY的最大值為 imageViewHeight - cellHeight。

因此可得如下公式:

cellOffset/tableViewHeight = imageViewOffset/(imageViewHeight - cellHeight);

imageViewOffset = cellOffset/tableViewHeight * (imageViewHeight - cellHeight);

好了,啰嗦完了,上代碼:

新建一個工程,在工程中自定義一個cell,cell中放一個UIImageView控件,讓UIImageView控件的高度大于Cell的高度。我這里設置為300;cell的高度設為200;

并且增加兩個方法:

// 獲取圖片最大偏移量
    - (CGFloat)imageOverflowHeight;
    // 重新設置圖片偏移量
    - (void)setImageOffset:(CGPoint)imageOffset;

自定義cell.m中的代碼如下:

-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

        if (self) {

            _mainImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width , 300)];

            _mainImageView.contentMode = UIViewContentModeScaleAspectFill;

            [self.contentView addSubview:_mainImageView];

            _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, [UIScreen mainScreen].bounds.size.width, 40)];

            _titleLabel.backgroundColor = [UIColor colorWithRed:0.94 green:0.94 blue:0.94 alpha:0.50];

            _titleLabel.text = @"這是圖片上的文字";

            _titleLabel.textAlignment = 1;

            [self.contentView addSubview:_titleLabel];
        }

        return self;
    }

    /**
     *  返回圖片大于imageView的高度
     *
     *  @return 圖片大于imageView的高度
     */
    - (CGFloat)imageOverflowHeight
    {
        // 減200 是因為cell的高度設為200,所以直接寫固定值了
        return _mainImageView.frame.size.height - 200;
    }

    /**
     *  設置imageView偏移量
     *
     *  @param imageOffset 偏移量
     */
    - (void)setImageOffset:(CGPoint)imageOffset
    {
        CGRect frame = _mainImageView.frame;
        frame.origin = imageOffset;
        _mainImageView.frame = frame;
    }

在VC中添加一個tableview控件,工程中拖入一些圖片備用。VC.m的代碼如下:

@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
    @property (nonatomic, strong) NSMutableArray *sourceArr;
    @property (nonatomic, strong) UITableView *mainTable;
    @end

    @implementation ViewController

    - (void)viewDidLoad {
        [super viewDidLoad];

        _sourceArr = [NSMutableArray array];

        for (NSInteger i = 1; i <= 44; i++) {

                NSString *imageName = [NSString stringWithFormat:@"img%ld.jpg", i];

                [_sourceArr addObject:imageName];

        }

        _mainTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];

        _mainTable.delegate = self;

        _mainTable.dataSource = self;

        _mainTable.separatorStyle = UITableViewCellSeparatorStyleNone;

        [_mainTable registerClass:[LTParallaxCell class] forCellReuseIdentifier:@"cell"];

        [self.view addSubview:_mainTable];


    }

    /**
     *  設置imageView的偏移量
     *
     *  @param cell
     */
    - (void)updateImageViewCellOffset:(LTParallaxCell *)cell
    {
        // 獲取cell的偏移量
        CGFloat cellOffset = cell.frame.origin.y - self.mainTable.contentOffset.y;
        // 獲取imageView的最大偏移量
         CGFloat imgMaxHeight = [cell imageOverflowHeight];
        // 計算imageView新的偏移量
         CGFloat offset = 0.0f - imgMaxHeight * cellOffset / self.mainTable.frame.size.height;
        // 設置imageView新的偏移量
        [cell setImageOffset:CGPointMake(0.0f, offset)];

    }

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return [_sourceArr count];
    }

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        LTParallaxCell *cell        = [tableView dequeueReusableCellWithIdentifier:@"cell"];

        cell.mainImageView.image    = [UIImage imageNamed:[_sourceArr objectAtIndex:indexPath.row]];

        cell.selectionStyle         = UITableViewCellSelectionStyleNone;

        cell.clipsToBounds          = YES;

        return cell;
    }

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return 200;
    }

    #pragma mark - UIScrollViewdelegate methods

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        for (LTParallaxCell *cell in self.mainTable.visibleCells) {
            [self updateImageViewCellOffset:cell];
        }
    }

    #pragma mark - UITableViewDelegate

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [self updateImageViewCellOffset:(LTParallaxCell *)cell];
    }

    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

    @end

至此,一個視差效果就完成了,如果有什么錯誤的地方歡迎大家指正。

 

來自:http://www.jianshu.com/p/00f069c91bea

 

 本文由用戶 yuud2866 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!