2016-03-21 11 views
7

Ich bin zum ersten Mal mit UICollectionView nicht sicher, wie dies zu tun ist. Ich versuche, eine App für TVOS zu erstellen und möchte das Menü wie airbnb tvos App anzeigen. Ich habe irgendwie versucht, dieses bestimmte Format zu erreichen, aber das Problem ist über den ersten Auftritt, weil der erste Auftritt auf Standardpunkten, d. H. 0,0 der Sammlungsansicht stattfindet, was zu einem Durcheinander führt. Heres mein Code was ich bisher gemacht habe.Richten Sie die Zelle in der Mitte (horizontal) in UICollectionView

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 
    if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as? ShowCell { 
    menuData = dataArray[indexPath.row] as! NSDictionary 
    cell.configureCell(menuData.objectForKey("name") as! String) 

    return cell 
    } 
    else { 
    return ShowCell() 
    } 
} 

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) { 
    if let previousItem = context.previouslyFocusedView as? ShowCell { 
    UIView.animateWithDuration(0.2, animations: {() -> Void in 
     previousItem.showImg.frame.size = self.originalCellSize 
    }) 
    } 
    if let nextItem = context.nextFocusedView as? ShowCell { 
    UIView.animateWithDuration(0.2, animations: {() -> Void in 
     nextItem.showImg.frame = CGRectMake(
            self.view.frame.width/2 - self.focusCellSize.width/2, 
            169.0, 
            self.focusCellSize.width, 
            self.focusCellSize.height) 

    }) 
    } 
} 

Dies ist die Ansicht, die ich erreichen möchte, und ich habe es erreicht, aber für die spätere Indizes bedeutet Index nach 1,2 enter image description here

Dies ist das Startverhalten, wenn es erscheint das erste Mal, und wenn ich die Kontrolle, um es bewegen sie wie diese enter image description here

geschieht

enter image description here

Das ist, was ich eigentlich will, aber ich kämpfe darin, meine fokussierte Zelle in die Mitte des Bildschirms zu bekommen und ähnlich meine vorherige und nächste auf beiden Seiten. Ich weiß, dass ich Rahmenkoordinaten explizit gebe, die nicht korrekt sind, das war nur ein Testfall, den ich lief und nichts anderes aber ich konnte den Weg nicht finden

+0

Würde nicht Einstellung 'adjustsImageWhenAncestorFocused' auf das Bild, um den Job in Ihrem Fall außer Kraft zu setzen? –

+0

habe das noch nicht probiert, aber die Sache ist, ich habe kein Bild gesetzt nur ich muss alle Zellen reparieren! –

+0

Warum verwenden Sie nicht einen UIpageViewController anstelle von CollectionView? Mit dem, was Sie erreichen möchten, mit horizontalem Scrollen und Animation zwischen den Elementen scheint es, dass dies die bessere Wahl für Sie ist. Alles, was Sie tun müssen, ist, die Ansicht (ähnlich einer Sammlungszelle) zu strukturieren, die verwendet werden würde, d. H. Geben Sie ihr das Bild und die Beschriftung, dann behandelt der Controller die Animation und den Paging. https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIPageViewControllerClassReferenceClassRef/ –

Antwort

3

Ich würde den Fokus und den Sammlungsinhalt steuern Offset (Scroll-Position) getrennt.

Für den Inhalt Offset sollten Sie die Abschnittsränder und den Abstand zwischen den Elementen festlegen, so dass Sie eine Zelle zentriert und die angrenzenden Zellen an den Rändern sichtbar haben. Sie können dieses Setup erhalten und testen, ohne einen Fokus zu zeigen.

Vermutlich ist es schwierig, das Objekt beim Scrollen (der Fokus ändert sich) genau in die Mitte zu bewegen. Um dies zu beheben, implementieren Sie - scrollViewWillEndDragging:withVelocity:targetContentOffset:, um das Element unter der targetContentOffset zu finden und seinen Mittelpunkt (aus den Layoutattributen) zu erhalten. Damit können Sie die targetContentOffset so ändern, dass die Schriftrolle genau mit dem Objekt zentriert endet.

Nun sollte der Fokus von der Zelle selbst verwaltet werden, nicht von der Sammlungsansicht. Unten ist ein (etwas großes) Beispiel für eine Animation zur Änderung des Zellenfokus. Es verwendet Kartografie, um Einschränkungen der Bildansicht zu ändern, und wendet eine Transformation auf ein Label an. Sie können etwas Ähnliches tun, je nachdem, wie das Bild und das Label miteinander interagieren sollen.

Beachten Sie, dass der folgende Code auch eine Bewegungseffekt-Transformation gilt, die dem von Apple gelieferten Bestand ähnelt, wenn ein UIImageView Fokus hat und adjustsImageWhenAncestorFocused festgelegt ist. Wenn Sie das nicht möchten, können Sie den Code ein wenig vereinfachen und verkürzen.

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) { 
    super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator) 

    if (context.nextFocusedView == self) { 
     UIView.animateWithDuration(0.1, 
      animations: {() -> Void in 
       self.imageConstraints = constrain(self.itemImageView, replace: self.imageConstraints!) { 
        $0.top == $0.superview!.top 
        $0.bottom == $0.superview!.bottom 
        $0.leading == $0.superview!.leading 
        $0.trailing == $0.superview!.trailing 
       } 
       self.itemLabel.transform = CGAffineTransformMakeTranslation(0, 60) 
       self.itemLabel.layer.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0).CGColor 

       self.layer.shadowOpacity = 1 

       self.layoutIfNeeded() 
      }, completion: nil) 

     let minMaxAngle = 10.0 
     let m34 = CGFloat(1.0/-1250) 
     let angle = CGFloat(minMaxAngle * M_PI/180.0) 

     var baseTransform = CATransform3DIdentity 
     baseTransform.m34 = m34 

     let rotateXmin = CATransform3DRotate(baseTransform, -1 * angle, 1.0, 0.0, 0.0); 
     let rotateXmax = CATransform3DRotate(baseTransform, angle, 1.0, 0.0, 0.0); 
     let rotateYmin = CATransform3DRotate(baseTransform, angle, 0.0, 1.0, 0.0); 
     let rotateYmax = CATransform3DRotate(baseTransform, -1 * angle, 0.0, 1.0, 0.0); 

     let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform", 
      type: .TiltAlongVerticalAxis) 
     verticalMotionEffect.minimumRelativeValue = NSValue(CATransform3D: rotateXmin) 
     verticalMotionEffect.maximumRelativeValue = NSValue(CATransform3D: rotateXmax) 

     let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform", 
      type: .TiltAlongHorizontalAxis) 
     horizontalMotionEffect.minimumRelativeValue = NSValue(CATransform3D: rotateYmin) 
     horizontalMotionEffect.maximumRelativeValue = NSValue(CATransform3D: rotateYmax) 

     let group = UIMotionEffectGroup() 
     group.motionEffects = [horizontalMotionEffect, verticalMotionEffect] 

     self.addMotionEffect(group) 

    } 
    else { 
     UIView.animateWithDuration(0.3, 
      animations: {() -> Void in 
       self.imageConstraints = constrain(self.itemImageView, replace: self.imageConstraints!) { 
        $0.top == $0.superview!.top + 20 
        $0.bottom == $0.superview!.bottom - 20 
        $0.leading == $0.superview!.leading + 20 
        $0.trailing == $0.superview!.trailing - 20 
       } 
       self.itemLabel.transform = CGAffineTransformIdentity 
       self.itemLabel.layer.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0.75).CGColor 

       self.layer.shadowOpacity = 0 

       self.layoutIfNeeded() 
      }, completion: nil) 

     for effect in self.motionEffects { 
      self.removeMotionEffect(effect) 
     } 
    } 
} 
+0

so las ich deine Antwort sehr sorgfältig. Sie haben Dinge kategorisiert, was in der Tat sehr hilfreich ist, selbst der erste Teil des Problems ist fast gelöst, aber ich kann die Zelle nicht zentrieren. Ich habe versucht wie mehrere Kombinationen, aber kein Glück. So zweiten Teil (die Beziehung von Bild und Label) geht gut :) Vielen Dank, aber immer noch warten auf Ihre Antwort auf Zellzentrum Sache .. –

+0

Ich habe mehr Details über den Teil hinzugefügt, ich denke, Sie haben ein Problem mit der genauen Endpunkt der Schriftrolle. – Wain

0

@Wain hat bereits eine Leitlinie der genannten Art ist hier meine genaue Antwort auf dieses Ziel zu erreichen:

override func didUpdateFocusInContext(context: UIFocusUpdateContext, 
              withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) { 
     if let focusedView = context.nextFocusedView as? ShowCell { 
      collectionView.scrollEnabled = false 
      let indexPath = collectionView.indexPathForCell(focusedView)! 
      focusedView.showImg.frame.size = self.focusImageSize 
      focusedView.showLbl.frame.size = self.focusLabelSize 
      focusedView.showLbl.font = UIFont.systemFontOfSize(75) 


      collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredHorizontally, animated: true) 
      self.collectionView.layoutIfNeeded() 
     } 
     else if let lastFocuedView = context.previouslyFocusedView as? ShowCell{ 


      collectionView.scrollEnabled = true 
      // let indexPath = collectionView.indexPathForCell(lastFocuedView)! 

      lastFocuedView.showImg.frame.size = self.originalImageSize 
      lastFocuedView.showLbl.frame.size = self.originalLabelSize 


      lastFocuedView.showLbl.font = UIFont.systemFontOfSize(70) 

      self.collectionView.layoutIfNeeded() 


     } 

und für die erste und die letzte Zelle, die Sie haben UIEdgeInsets zu geben (es ist ein Delegiertenmethode des Flusslayouts)

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets{ 

     return UIEdgeInsets(top: 0.0, left: self.collectionView.frame.width/2 , bottom: 0.0, right: self.collectionView.frame.width/2) 



    } 

Herzlichen Dank an Wain für die Bereitstellung einer genauen Richtlinie zu dieser Frage. Prost!

Verwandte Themen