2013-01-23 3 views
7

HintergrundiOS 6.0: UICollectionView nicht respektiert clipsToBounds mit pagingEnabled

Ich bin ein UICollectionView (zum ersten Mal) in dem Bemühen, die Implementierung einer ausgelagerten horizontalen Bildlauf Ansicht von Fliesen zu erreichen. Ich möchte, dass jede Kachel in der Mitte des Rahmens angezeigt wird, wobei die Schwesterkacheln teilweise links und rechts sichtbar sind (etwas wie die Seitenauswahl in der Safari-App). Ich interessiere mich für die Verwendung der UICollectionView, um die Vorteile der eingebauten Zellenentfernung auszunutzen und würde lieber keinen gedrehten UITableView verwenden.

Ausgabe

Das Problem, das ich finden bin, ist, dass, wenn pagingEnabled = YES und clipsToBounds = NO verwenden, die UICollectionView Zellen außerhalb des collectionView Rahmen entfernt (sie sind nicht in der visibleCells Array), sobald Paging abgeschlossen ist. Kann jemand Tipps geben, wie der Effekt der Anzeige von Vorschaubildern der Schwesterkacheln erreicht werden kann, während dieses grundlegende Setup beibehalten wird? Oder nähere ich mich dem falsch?

Screenshots

Start start scrolling Ende end

Das Scrollen Bildschirm scrollen ist genau richtig. Aber in den Anfangs- und Endaufnahmen möchte ich, dass sie in den blauen Rändern grün sichtbar sind.

Hier ist, was in meinem AppDelegate.m ist (Kredit tutsplus.com für die Grundeinstellungen hier):

#import "AppDelegate.h" 

@interface ViewController : UICollectionViewController 
@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"ID"]; 
    [self.view setBackgroundColor:[UIColor blueColor]]; 
    // pad the collection view by 20 px 
    UIEdgeInsets padding = UIEdgeInsetsMake(20.0, 20.0, 20.0, 20.0); 
    [self.collectionView setFrame:UIEdgeInsetsInsetRect(self.view.frame, padding)]; 
    // set pagingEnabled and clipsToBounds off 
    [self.collectionView setPagingEnabled:YES]; 
    [self.collectionView setClipsToBounds:NO]; 
} 

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 
    return 5; 
} 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ID" forIndexPath:indexPath]; 
    UILabel *label = [[UILabel alloc] initWithFrame:cell.bounds]; 
    label.textAlignment = NSTextAlignmentCenter; 
    label.text = [NSString stringWithFormat:@"%d", indexPath.row]; 
    [label setBackgroundColor:[UIColor greenColor]]; 
    [cell.contentView addSubview:label]; 
    return cell; 
} 
@end 

@implementation AppDelegate 
{ 
    ViewController *vc; 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    // setup the UICollectionViewFlowLayout 
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 
    layout.itemSize = CGSizeMake(280, 280); 
    layout.minimumInteritemSpacing = 0; 
    layout.minimumLineSpacing = 0; 
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 
    // add a custom UICollectionViewController to the window 
    vc = [[ViewController alloc] initWithCollectionViewLayout:layout]; 
    self.window.rootViewController = vc; 
    self.window.backgroundColor = [UIColor yellowColor]; 
    [self.window makeKeyAndVisible]; 
    return YES; 
} 
@end 

Antwort

9

Es stellte sich heraus, die Lösung für dieses Problem war eigentlich ziemlich einfach. Ich brauchte nur die UICollectionViewCell Zellen mit genügend Pixeln zu überlappen, damit sie immer noch innerhalb des collectionView-Rahmens angezeigt werden, nachdem das seitenweise Blättern beendet wurde. Der relevent Code war

layout.itemSize = CGSizeMake(300, 300); 
layout.minimumLineSpacing = -20.0; 

Und ich subclassed die UICollectionViewFlowLayout und überwog die (CGSize)collectionViewContentSize Methode, um die nicht-überlappenden Größe der Zellen zurückzukehren.

+0

Wir haben festgestellt, dass dies so lange funktioniert, bis Sie 6 oder mehr Zellen haben. An diesem Punkt beginnen die Zellen zu verschwinden, auch wenn sie sich innerhalb des Sichtrahmens befinden. Es passiert, wenn die fragliche Zelle * hinter * beiden Nachbarzellen ist (hier haben wir aufgehört zu untersuchen). –

+0

Ich kann dies nicht auf iOS 8, auf den neuen iPhone-Größen und unterstützt Auto-Layout funktionieren. –

0

Ich bin kein Experte in Kollektion, aber es könnte möglicherweise mit dieser Linie in cellForItemAtIndexPath sein zu tun:

Jedes Mal, wenn es aufgerufen wird, wird eine weitere Label-Unteransicht zur Zelle hinzugefügt. Entweder nach einem vorhandenen Label oder einer Unterklasse UICollectionViewCell suchen?

+0

Danke! Das Auskommentieren beeinflusst den Clipping-Bereich überhaupt nicht, löst also nicht das Kernproblem, sondern einen guten Haken. –

2

Vielen Dank für den Tipp über die Verwendung eines negativen minimumLineSpacing. Ich habe eine Testeranwendung erstellt, die eine aus einer XIB-Datei geladene Auflistungsansichtszelle verwendet. Die Zelle hat einen transparenten Hintergrund und eine "innere" Ansicht für den Inhalt der Zelle.

Auf diese Weise ist kein benutzerdefiniertes Ablauflayout erforderlich.

https://github.com/j4johnfox/CollectionViewTester

0

Sie wollen auch -pointInside:withEvent: außer Kraft zu setzen Scroll-Gesten zu ermöglichen, außerhalb des Rahmens der Sammlung Ansicht zu starten. Ich mit diesem eine UIEdgeInsets Eigenschaft in meiner Sammlung Ansicht Unterklasse:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { 
    CGRect extendedBounds = UIEdgeInsetsInsetRect(self.bounds, self.touchAreaInsets); 

    return CGRectContainsPoint(extendedBounds, point); 
} 

Wenn Sie keine App Store Sicherheit benötigen, können Sie _visibleBounds außer Kraft setzen können negative Abstände Hacks zu vermeiden:

- (CGRect)_visibleBounds { 
    return UIEdgeInsetsInsetRect(self.bounds, self.touchAreaInsets); 
} 

Wenn Sie‘ re nicht auch auf Codegröße gedrückt und App Store Sicherheit benötigen Sie könnten auch PSTCollectionView Unterklasse und möglicherweise visibleBoundRects für den gleichen Effekt überschreiben.

Verwandte Themen