OK, la réponse est non, il n'y a aucun moyen de le faire sans sous-classer UICollectionViewFlowLayout.
Cependant, le sous-classement est incroyablement facile pour quiconque lira ceci à l'avenir.
J'ai d'abord configuré l'appel de sous-classe MyCollectionViewFlowLayout
, puis dans le générateur d'interface, j'ai changé la disposition de la vue de collection sur Personnalisée et sélectionné ma sous-classe de disposition de flux.
Parce que vous le faites de cette façon, vous ne pouvez pas spécifier la taille des éléments, etc ... dans IB donc dans MyCollectionViewFlowLayout.m j'ai ceci ...
- (void)awakeFromNib
{
self.itemSize = CGSizeMake(75.0, 75.0);
self.minimumInteritemSpacing = 10.0;
self.minimumLineSpacing = 10.0;
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.sectionInset = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
}
Cela configure toutes les tailles pour moi et la direction de défilement.
Ensuite ...
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalOffset = proposedContentOffset.x + 5;
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray *array = [super layoutAttributesForElementsInRect:targetRect];
for (UICollectionViewLayoutAttributes *layoutAttributes in array) {
CGFloat itemOffset = layoutAttributes.frame.origin.x;
if (ABS(itemOffset - horizontalOffset) < ABS(offsetAdjustment)) {
offsetAdjustment = itemOffset - horizontalOffset;
}
}
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}
Cela garantit que le défilement se termine par une marge de 5,0 sur le bord gauche.
C'est tout ce que j'avais à faire. Je n'avais pas du tout besoin de définir la disposition du flux dans le code.
targetContentOffsetForProposedContentOffset:withVelocity
n'est pas appelé pour moi quand je fais défiler. Que se passe-t-il?La solution de Dan est imparfaite. Il ne gère pas bien le feuilletage de l'utilisateur. Les cas où l'utilisateur feuillette rapidement et que le défilement ne bougeait pas tellement, ont des problèmes d'animation.
Ma mise en œuvre alternative proposée a la même pagination que celle proposée précédemment, mais gère le feuilletage de l'utilisateur entre les pages.
la source
Version rapide de la réponse acceptée.
Valable pour Swift 5 .
la source
Voici mon implémentation dans Swift 5 pour la pagination verticale basée sur les cellules:
Quelques notes:
itemSize
correspond réellement à la taille de l'élément car c'est souvent un problème, en particulier lors de l'utilisationcollectionView(_:layout:sizeForItemAt:)
, utilisez plutôt une variable personnalisée avec le itemSize.self.collectionView.decelerationRate = UIScrollView.DecelerationRate.fast
.Voici une version horizontale (je ne l'ai pas testée à fond, veuillez pardonner toute erreur):
Ce code est basé sur le code que j'utilise dans mon projet personnel, vous pouvez le vérifier ici en le téléchargeant et en exécutant la cible Exemple.
la source
Bien que cette réponse m'ait été d'une grande aide, il y a un scintillement perceptible lorsque vous glissez rapidement sur une petite distance. Il est beaucoup plus facile de le reproduire sur l'appareil.
J'ai trouvé que cela arrive toujours quand
collectionView.contentOffset.x - proposedContentOffset.x
etvelocity.x
chante différemment.Ma solution était de m'assurer que
proposedContentOffset
c'est plus quecontentOffset.x
si la vitesse est positive, et moins si elle est négative. C'est en C # mais devrait être assez simple à traduire en Objective C:Ce code utilise
MinContentOffset
,MaxContentOffset
etSnapStep
qui devrait être simple à définir. Dans mon cas, ils se sont avérés êtrela source
Après de longs tests, j'ai trouvé une solution pour s'aligner au centre avec une largeur de cellule personnalisée (chaque cellule a une largeur différente) qui corrige le scintillement. N'hésitez pas à améliorer le script.
la source
se référer à cette réponse de Dan Abramov voici la version Swift
ou gist ici https://gist.github.com/katopz/8b04c783387f0c345cd9
la source
Pour tous ceux qui recherchent une solution qui ...
collectionView.contentInset
(et safeArea sur iPhone X)alors s'il vous plaît voir ci-dessous ...
la source
Voici ma solution Swift sur une vue de collection à défilement horizontal. C'est simple, doux et évite tout scintillement.
la source
itemSize
??pageWidth()
devrait utiliserminimumLineSpacing
car il défile horizontalement. Et dans mon cas, j'ai une vuecontentInset
pour la collection afin que la première et la dernière cellule puissent être centrées, donc j'utiliselet xOffset = pageWidth() * index - collectionView.contentInset.left
.un petit problème que j'ai rencontré lors de l'utilisation de targetContentOffsetForProposedContentOffset est un problème avec la dernière cellule ne s'ajustant pas en fonction du nouveau point que j'ai renvoyé.
J'ai découvert que le CGPoint que j'ai retourné avait une valeur Y plus grande que celle autorisée, j'ai donc utilisé le code suivant à la fin de mon implémentation targetContentOffsetForProposedContentOffset:
juste pour que ce soit plus clair, voici mon implémentation de mise en page complète qui imite simplement le comportement de pagination verticale:
j'espère que cela permettra à quelqu'un d'économiser du temps et des maux de tête
la source
Je préfère permettre à l'utilisateur de parcourir plusieurs pages. Voici donc ma version de
targetContentOffsetForProposedContentOffset
(basée sur la réponse de DarthMike) pour la mise en page verticale .la source
La réponse de Fogmeisters a fonctionné pour moi à moins que je ne fasse défiler jusqu'à la fin de la rangée. Mes cellules ne s'adaptent pas parfaitement à l'écran, il défilerait donc jusqu'à la fin et reviendrait en arrière avec une secousse de sorte que la dernière cellule chevauche toujours le bord droit de l'écran.
Pour éviter cela, ajoutez la ligne de code suivante au début de la méthode targetcontentoffset
la source
@ André Abreu Code d'
Version Swift3
la source
Swift 4
La solution la plus simple pour la vue de collection avec des cellules de taille unique (défilement horizontal):
la source
Une solution plus courte (en supposant que vous mettez en cache vos attributs de mise en page):
Pour mettre cela en contexte:
la source
Pour m'assurer que cela fonctionne dans la version Swift (swift 5 maintenant), j'ai utilisé la réponse de @ André Abreu, j'ajoute quelques informations supplémentaires:
Lors du sous-classement de UICollectionViewFlowLayout, la fonction "override func awakeFromNib () {}" ne fonctionne pas (je ne sais pas pourquoi). Au lieu de cela, j'ai utilisé "override init () {super.init ()}"
Voici mon code mis dans la classe SubclassFlowLayout: UICollectionViewFlowLayout {}:
Après le sous-classement, assurez-vous de mettre ceci dans ViewDidLoad ():
la source
Pour ceux qui recherchent une solution dans Swift:
la source
Voici une démo pour la pagination par cellule (lorsque vous faites défiler rapidement, ne sautez pas une ou plusieurs cellules): https://github.com/ApesTalk/ATPagingByCell
la source