2010-03-19 52 views
2

想象一下,您有一個普通的桌子視圖,其中每行是傳送帶上的物品。您將把這些項目放在表格視圖的每個單元格中,但是當您滾動時,您還希望背景圖像(傳送帶)也滾動。你怎麼能這樣做?如何實現一個TableView同時滾動的背景?

回答

2

UITableView背景透明,並添加它後面的UIScrollView與它裏面的UIImageView。爲UITableView滾動時添加一個偵聽器(因爲它是UIScrollView的子類,它具有所有相同的委託方法)。然後,當它滾動時,將它後面的UIScrollView的滾動位置設置爲以編程方式相同。

如果你想扭轉偏移值,你可以在UITableView的後面沒有第二個UIScrollView,只需要一個普通的UIIImageView即可。

+0

那會是哪種代表方法?我看着scorllViewDelegate,並沒有發現任何會在它滾動時被調用的東西。另外,考慮到你會每秒重新調整圖像位置多次,會不會出現巨大的性能問題? – erotsppa 2010-03-30 22:54:02

+0

真的沒有性能問題,沒有。你不重繪任何東西,所以你應該沒問題。至於委託方法,scrollViewDidScroll如何: – 2010-03-31 03:29:56

+2

你不能真正完全同步兩個UIScrollViews,完成與decembleration和彈跳。 – steipete 2011-09-01 17:02:49

5

您應該能夠通過設置表視圖的背景顏色來實現:

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

儘管這會起作用,但只有當您有一幅純色圖像時,這纔會有用。假設你是一個人的圖像,那麼它會在表格視圖單元格中看起來非常扭曲 – 2010-03-20 04:21:31

+0

是否有另一個(合理的)替代方案,因爲OP希望背景使用*表格視圖滾動*我無法想象自己。 – 2010-03-20 05:11:38

+0

這是一個很好的解決方案,可以適應您的需求。所以你的形象不應該縮放?考慮UIImage的'resizableImageWithCapInsets:resizingMode:'(特別是在平鋪模式下)。或者,在某些時候在圖像上繪製一些可重複的(也許只是黑色的)背景。 – Timo 2013-02-04 12:07:22

1

我沒有嘗試過這一點,所以我不知道最好的方法是什麼,但一選項是將背景圖像作爲UIImageView添加到每個單元格,以便每個單元格都具有背景圖像的全尺寸副本。將單元格中的clipsToBounds設置爲NO,並將UIImageView的邊界設置爲負y值,該y值等於從單元格到表格頂部的偏移量。

您可能還想考慮使用UIScrollView而不是UITableView。這個UITableView本身就是一個UIScrollView,所以你可以嘗試添加你的背景圖像作爲你的UITableView的一個子視圖,但是如果這能工作,我會感到很驚訝。我猜UITableView實現不會和國外的子視圖一起玩。

**編輯**

雖然我仍然懷疑的UIScrollView可能是一個更合適的基類,用在這裏,我決定試試我上述的UIImageView伎倆。這很簡單,只要所有的UIImageView共享一個UIImage就不會消耗過多的內存。這裏是我的示例代碼:

// 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 
+0

真的不是一個很好的解決方案,每個單元格都有一個完整的圖像拷貝將導致大量不必要的內存消耗,並且由於'UITableViewCell'被回收,需要大量的代碼來管理哪個背景顯示單元何時進入視圖。然而,使用UIScrollView可能是一個更好的主意。 – Jasarien 2010-03-29 16:27:39

+1

實際上,只要所有的UIImageView共享相同的UIImage,就不會消耗過多的內存。我用320 x 2719的圖像測試了這個圖像,這需要超過3.4 MB的圖像緩衝區。從5行到46個可見行只消耗額外的57.4 K,這表明開銷來自對象分配,而不是重複的圖像緩衝區。我將編輯併發布我的代碼。 – cduhn 2010-03-31 23:55:25

0

我的建議是類似於埃德馬蒂(他認爲「沒有第二個UIScrollView的」什麼):

放置UITableView的一個簡單的UIView裏面。使單元格背景透明,以便從桌面下方的背景顯示

在UITableView的下方,放置一個具有所需背景的UIImageView。 UITableView和UIImageView現在都位於相同的封閉UIView中。

收聽UITableView的滾動事件。當檢測到滾動時,只需簡單地更改背景UIImageView位置(frame.origin.y),以便它「堅持」tableview。

您可以將背景作爲一個巨大的圖像,或者有一系列的背景,因此您可以平鋪。您可以獲得一組圖像,並在需要時從頂部/底部添加到陣列中,還可以從屏幕上移除已「滾動」的圖像以節省內存。您需要自己計算所有這些背景圖像的位置,但沒有什麼複雜的。

+0

那會是哪種代表方法?我看着scorllViewDelegate,並沒有發現任何會在它滾動時被調用的東西。另外,考慮到你會每秒重新調整圖像位置多次,會不會出現巨大的性能問題? – erotsppa 2010-03-30 22:54:46

+0

scrollViewDidScroll:(http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIScrollViewDelegate_Protocol/Reference/UIScrollViewDelegate.html#//apple_ref/doc/uid/TP40006923-CH3-SW3)每當調用tableview卷軸。在滾動過程中可能會調用很多次。 /性能有很多因素,您只需在設備上進行測試即可在實際應用中查看它。 – Jaanus 2010-03-31 15:21:38