开发者

How to implement a TableView where the background scrolls at the same time?

开发者 https://www.devze.com 2022-12-23 18:51 出处:网络
Imagine you have a normal table view where each row is an item on a conveyor belt. You will put the items in each cell of the table view but when you scroll you also want the background image (the con

Imagine you have a normal table view where each row is an item on a conveyor belt. You will put the items in each cell of the table view but when you scroll you also want the background image (the conveyor belt) to scrol开发者_如何转开发l as well. How can you do this?


You should be able to accomplish this by setting the background color of the table view:

tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background.png"]];


Have the UITableView background transparent, and add a UIScrollView behind it with the UIImageView inside it. Add a listener for when the UITableView scrolls (since it is a subclass of UIScrollView it has all the same delegate methods). Then, when it scrolls, set the scroll position of the UIScrollView behind it to the same programmatically.

You could technically do it without a second UIScrollView behind the UITableView, just with a plain UIIImageView, if you want to reverse the offset values.


I haven't tried this, so I'm not sure what the best approach would be, but one option would be to add your background image as a UIImageView to each of your cells so that every cell has a full-sized copy of your background image. Set clipsToBounds to NO on your cell, and give the bounds of the UIImageView a negative y value equal to the offset from your cell to the top of the table.

You may also want to consider using UIScrollView instead of UITableView.

UITableView is itself a UIScrollView, so you could try just adding your background image as a subview of your UITableView, but I'd be surprised if that worked. I'm guessing the UITableView implementation won't play nice with foreign subviews.

** EDIT **

While I still suspect that UIScrollView may be a more appropriate base class to use here, I decided to try the UIImageView trick I described above. It's fairly simple and doesn't consume excessive memory as long as all your UIImageViews share a single UIImage. Here's my sample code:

//  LadderCell.h
#import <UIKit/UIKit.h>

@interface LadderCell : UITableViewCell {
    UIImageView *backgroundImageView;
    UILabel *titleLabel;
}

@property (nonatomic, retain) UIImageView *backgroundImageView;
@property (nonatomic, retain) UILabel *titleLabel;

- (void)setIndexPath:(NSIndexPath *)indexPath;
- (id)initWithImage:(UIImage *)theImage;
+ (NSString *)reuseIdentifier;
+ (CGFloat)height;
@end
//  LadderCell.m
#import "LadderCell.h"

@implementation LadderCell
@synthesize backgroundImageView, titleLabel;

- (void)dealloc {
    self.backgroundImageView = nil;
    self.titleLabel = nil;
    [super dealloc];
}

- (id)initWithImage:(UIImage *)theImage {
    if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[LadderCell reuseIdentifier]]) {
        self.frame = CGRectMake(0.0, 0.0, 320.0, [LadderCell height]);
        self.clipsToBounds = YES;
        self.backgroundImageView = [[[UIImageView alloc] initWithImage:theImage] autorelease];
        backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
        self.titleLabel = [[[UILabel alloc] initWithFrame:self.bounds] autorelease];
        titleLabel.textAlignment = UITextAlignmentCenter;
        titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        titleLabel.backgroundColor = [UIColor colorWithWhite:1 alpha:0];
        [self addSubview:backgroundImageView];
        [self addSubview:titleLabel];
    }
    return self;
}

- (void)setIndexPath:(NSIndexPath *)indexPath {
    backgroundImageView.frame = CGRectMake(0.0, 
                                           -(CGFloat)indexPath.row * [LadderCell height] + 100.0,  
                                           backgroundImageView.frame.size.width,
                                           backgroundImageView.frame.size.height);
}

+ (NSString *)reuseIdentifier {
    return @"LadderCell";
}

+ (CGFloat)height {
    return 30;

}

@end
//  TableBackgroundTestViewController.h
#import 

@interface TableBackgroundTestViewController : UITableViewController {
    UIImage *backgroundImage;
}

@property (nonatomic, retain) UIImage *backgroundImage;

@end
//  TableBackgroundTestViewController.m
#import "TableBackgroundTestViewController.h"
#import "LadderCell.h"

@implementation TableBackgroundTestViewController
@synthesize backgroundImage;

- (void)dealloc {
    self.backgroundImage = nil;
    [super dealloc];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.backgroundImage = [UIImage imageNamed:@"background.png"];
}

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

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

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [LadderCell height];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    LadderCell *cell = (LadderCell *)[tableView dequeueReusableCellWithIdentifier:[LadderCell reuseIdentifier]];
    if (!cell) {
        cell = [[[LadderCell alloc] initWithImage:self.backgroundImage] autorelease];
    }
    [cell setIndexPath:indexPath];
    cell.titleLabel.text = [NSString stringWithFormat:@"Row %d", indexPath.row];
    return cell;
}

@end


My suggestion is similar to Ed Marty (what he suggests "without a second UIScrollView"):

Place the UITableView inside a simple UIView. Make the cell backgrounds transparent so background from below the tableview would show

Below the UITableView, place an UIImageView with your desired background. Both the UITableView and UIImageView now sit inside the same enclosing UIView.

Listen to scroll events of UITableView. When detecting a scroll, simply change the background UIImageView position (frame.origin.y) appropriately, so that it would "stick with" the tableview.

You can have the background as one gigantic image, or have a series of them so you do tiling. You can have an array of the images and add to the array from top/bottom when needed, and also remove the images that have "scrolled away" from screen to conserve memory. You will need to calculate the positions for all these background images yourself, but there's nothing complicated in that.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号