OK, odpowiedź brzmi: nie, nie da się tego zrobić bez podklasy UICollectionViewFlowLayout.
Jednak tworzenie podklas jest niezwykle łatwe dla każdego, kto czyta to w przyszłości.
Najpierw skonfigurowałem wywołanie podklasy, MyCollectionViewFlowLayout
a następnie w konstruktorze interfejsu zmieniłem układ widoku kolekcji na Niestandardowy i wybrałem podklasę układu przepływu.
Ponieważ robisz to w ten sposób, nie możesz określić rozmiarów elementów itp ... w IB, więc w MyCollectionViewFlowLayout.m mam to ...
- (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);
}
To ustawia dla mnie wszystkie rozmiary i kierunek przewijania.
Następnie ...
- (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);
}
Gwarantuje to, że przewijanie kończy się marginesem 5,0 na lewej krawędzi.
To wszystko, co musiałem zrobić. W ogóle nie musiałem ustawiać układu przepływu w kodzie.
targetContentOffsetForProposedContentOffset:withVelocity
nie jest do mnie wzywany, kiedy przewijam. Co się dzieje?Rozwiązanie Dana jest wadliwe. Nie radzi sobie dobrze z przesuwaniem użytkownika. Przypadki, w których użytkownik szybko klika, a scroll nie poruszał się tak bardzo, mają usterki animacji.
Proponowana przeze mnie alternatywna implementacja ma taką samą paginację jak poprzednio, ale obsługuje przeskakiwanie między stronami.
źródło
Szybka wersja zaakceptowanej odpowiedzi.
Obowiązuje dla Swift 5 .
źródło
Oto moja implementacja w Swift 5 do stronicowania pionowego opartego na komórkach:
Kilka uwag:
itemSize
faktycznie pasuje on do rozmiaru przedmiotu, ponieważ często stanowi to problem, zwłaszcza podczas używaniacollectionView(_:layout:sizeForItemAt:)
, zamiast tego użyj niestandardowej zmiennej z itemSize.self.collectionView.decelerationRate = UIScrollView.DecelerationRate.fast
.Oto wersja pozioma (nie przetestowałem jej dokładnie, więc proszę wybaczyć wszelkie błędy):
Ten kod jest oparty na kodzie, którego używam w moim osobistym projekcie, możesz go sprawdzić tutaj , pobierając go i uruchamiając przykładowy cel.
źródło
Chociaż ta odpowiedź była dla mnie bardzo pomocna, zauważalne jest migotanie podczas szybkiego przesuwania na niewielkiej odległości. O wiele łatwiej jest odtworzyć go na urządzeniu.
Odkryłem, że to zawsze się dzieje
collectionView.contentOffset.x - proposedContentOffset.x
ivelocity.x
ma różne śpiewa.Moje rozwiązanie polegało na upewnieniu się, że
proposedContentOffset
jest to więcej niż wcontentOffset.x
przypadku prędkości dodatniej, a mniejsze, jeśli jest ujemne. Jest w C #, ale powinno być dość proste do przetłumaczenia na Objective C:Ten kod jest używany
MinContentOffset
,MaxContentOffset
aSnapStep
jego zdefiniowanie powinno być proste. W moim przypadku okazali sięźródło
Po długich testach znalazłem rozwiązanie polegające na przyciągnięciu do środka z niestandardową szerokością komórki (każda komórka ma różną szerokość), co eliminuje migotanie. Zapraszam do ulepszania skryptu.
źródło
odwołaj się do tej odpowiedzi Dana Abramova tutaj wersja Swift
lub podsumuj tutaj https://gist.github.com/katopz/8b04c783387f0c345cd9
źródło
Dla każdego, kto szuka rozwiązania, które ...
collectionView.contentInset
(i safeArea na iPhonie X)zobacz poniżej ...
źródło
Oto moje rozwiązanie Swift w widoku kolekcji przewijanym w poziomie. Jest prosty, słodki i zapobiega migotaniu.
źródło
itemSize
??pageWidth()
powinien używać,minimumLineSpacing
ponieważ przewija się poziomo. W moim przypadku mamcontentInset
widok kolekcji, aby można było wyśrodkować pierwszą i ostatnią komórkę, więc używamlet xOffset = pageWidth() * index - collectionView.contentInset.left
.mały problem, który napotkałem podczas korzystania z targetContentOffsetForProposedContentOffset, to problem z ostatnią komórką, która nie dostosowywała się do nowego punktu, który zwróciłem.
Dowiedziałem się, że CGPoint, który zwróciłem, miał wartość Y większą niż dozwolona, więc użyłem następującego kodu na końcu mojej implementacji targetContentOffsetForProposedContentOffset:
żeby było jaśniej, oto moja pełna implementacja układu, która po prostu imituje zachowanie stronicowania w pionie:
miejmy nadzieję, że zaoszczędzi to komuś czasu i bólu głowy
źródło
Wolę, aby użytkownik mógł przeglądać kilka stron. Oto moja wersja
targetContentOffsetForProposedContentOffset
(oparta na odpowiedzi DarthMike) dla układu pionowego .źródło
Odpowiedź Fogmeister działała dla mnie, chyba że przewinęłam do końca wiersza. Moje komórki nie mieszczą się dokładnie na ekranie, więc przewijałyby się do końca i szarpały z powrotem, tak że ostatnia komórka zawsze zachodziła na prawą krawędź ekranu.
Aby temu zapobiec, dodaj następujący wiersz kodu na początku metody targetcontentoffset
źródło
Kod @ André Abreu
Wersja Swift3
źródło
Szybki 4
Najłatwiejsze rozwiązanie dla widoku kolekcji z komórkami o jednym rozmiarze (przewijanie w poziomie):
źródło
Krótsze rozwiązanie (zakładając, że buforujesz atrybuty układu):
Aby umieścić to w kontekście:
źródło
Aby upewnić się, że działa w wersji Swift (teraz Swift 5), skorzystałem z odpowiedzi od @ André Abreu, dodaję więcej informacji:
Podczas tworzenia podklas UICollectionViewFlowLayout, "override func awakeFromNib () {}" nie działa (nie wiem dlaczego). Zamiast tego użyłem „override init () {super.init ()}”
Oto mój kod umieszczony w klasie SubclassFlowLayout: UICollectionViewFlowLayout {}:
Po utworzeniu podklasy pamiętaj, aby umieścić to w ViewDidLoad ():
źródło
Dla szukających rozwiązania w Swift:
źródło
Oto demo do stronicowania według komórki (podczas szybkiego przewijania, nie pomijaj jednej lub więcej komórek): https://github.com/ApesTalk/ATPagingByCell
źródło