Domyślnie, gdy korzystasz z układu przepływu w widoku kolekcji, komórki są centrami w pionie. Czy istnieje sposób na zmianę tego dostosowania?Widok UICollection Układ przepływu Wyrównanie w pionie
Odpowiedz
następujący kod pracował dla mnie
@interface TopAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout
- (void)alignToTopForSameLineElements:(NSArray *)sameLineElements;
@end
@implementation TopAlignedCollectionViewFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;
{
NSArray *attrs = [super layoutAttributesForElementsInRect:rect];
CGFloat baseline = -2;
NSMutableArray *sameLineElements = [NSMutableArray array];
for (UICollectionViewLayoutAttributes *element in attrs) {
if (element.representedElementCategory == UICollectionElementCategoryCell) {
CGRect frame = element.frame;
CGFloat centerY = CGRectGetMidY(frame);
if (ABS(centerY - baseline) > 1) {
baseline = centerY;
[self alignToTopForSameLineElements:sameLineElements];
[sameLineElements removeAllObjects];
}
[sameLineElements addObject:element];
}
}
[self alignToTopForSameLineElements:sameLineElements];//align one more time for the last line
return attrs;
}
- (void)alignToTopForSameLineElements:(NSArray *)sameLineElements
{
if (sameLineElements.count == 0) {
return;
}
NSArray *sorted = [sameLineElements sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewLayoutAttributes *obj1, UICollectionViewLayoutAttributes *obj2) {
CGFloat height1 = obj1.frame.size.height;
CGFloat height2 = obj2.frame.size.height;
CGFloat delta = height1 - height2;
return delta == 0. ? NSOrderedSame : ABS(delta)/delta;
}];
UICollectionViewLayoutAttributes *tallest = [sorted lastObject];
[sameLineElements enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *obj, NSUInteger idx, BOOL *stop) {
obj.frame = CGRectOffset(obj.frame, 0, tallest.frame.origin.y - obj.frame.origin.y);
}];
}
@end
Testował szereg rozwiązań, to był jedyny działający zgodnie z oczekiwaniami. – Johannes
Z jakiegoś powodu czasem to by się zdarzyło, ale wtedy przewijałem i komórki uprzednio wyrównane byłyby wyśrodkowane. Bardzo dziwny. – rob5408
Tak, wydaje się działać, ale trochę dziwne. Wydaje się nie działać na iOS 9. Wszelkie sugestie, pomoc. dzięki – Frade
Klasa UICollectionViewFlowLayout
pochodzi z klasy UICollectionViewLayout
bazowej. A jeśli spojrzysz na documentation for that, zobaczysz, że istnieje wiele metod, które możesz zastąpić, a najbardziej prawdopodobnym kandydatem jest layoutAttributesForItemAtIndexPath:
.
Jeśli zastąpisz tę metodę, możesz pozwolić jej wywołać jej super implementację, a następnie dostosować właściwości zwróconego obiektu UICollectionViewLayoutAttributes
. W szczególności będziesz musiał dostosować właściwość frame
, aby zmienić położenie elementu, aby nie był już wycentrowany.
Dzięki, spróbuję z tym rozwiązaniem. –
To może lub nie może pracować dla danej sytuacji, ale miałem trochę szczęścia instacji UICollectionViewFlowLayout
w następujący sposób:
@interface CustomFlowLayout : UICollectionViewFlowLayout
@end
@implementation CustomFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) {
if (nil == attributes.representedElementKind) {
NSIndexPath* indexPath = attributes.indexPath;
attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
}
}
return attributesToReturn;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes *currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
currentItemAttributes.frame = CGRectOffset(currentItemAttributes.frame, 0, 0.5 * CGRectGetHeight(currentItemAttributes.frame));
return currentItemAttributes;
}
@end
@DongXu: Twój rozwiązanie zadziałało również dla mnie. Oto wersja SWIFT jeżeli:
class TopAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout
{
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]?
{
if let attrs = super.layoutAttributesForElementsInRect(rect)
{
var baseline: CGFloat = -2
var sameLineElements = [UICollectionViewLayoutAttributes]()
for element in attrs
{
if element.representedElementCategory == .Cell
{
let frame = element.frame
let centerY = CGRectGetMidY(frame)
if abs(centerY - baseline) > 1
{
baseline = centerY
TopAlignedCollectionViewFlowLayout.alignToTopForSameLineElements(sameLineElements)
sameLineElements.removeAll()
}
sameLineElements.append(element)
}
}
TopAlignedCollectionViewFlowLayout.alignToTopForSameLineElements(sameLineElements) // align one more time for the last line
return attrs
}
return nil
}
private class func alignToTopForSameLineElements(sameLineElements: [UICollectionViewLayoutAttributes])
{
if sameLineElements.count < 1
{
return
}
let sorted = sameLineElements.sort { (obj1: UICollectionViewLayoutAttributes, obj2: UICollectionViewLayoutAttributes) -> Bool in
let height1 = obj1.frame.size.height
let height2 = obj2.frame.size.height
let delta = height1 - height2
return delta <= 0
}
if let tallest = sorted.last
{
for obj in sameLineElements
{
obj.frame = CGRectOffset(obj.frame, 0, tallest.frame.origin.y - obj.frame.origin.y)
}
}
}
}
Możesz pozbyć się klauzuli 'if' wewnątrz pętli for w następujący sposób: dla elementu w attrs gdzie element.representElementCategory == .cell {. . . } – kikettas
Użyłem tego kodu (https://github.com/yoeriboven/TopAlignedCollectionViewLayout) po rozwiązanie Dongxu za nie do końca pracy. Jedyną modyfikacją było, że to pierwotnie zaprojektowane do użytku z siatką, więc potrzebne do wystąpienia układ o dowolnie dużej liczbie kolumny ...
let collectionViewFlowLayout = YBTopAlignedCollectionViewFlowLayout(numColumns: 1000)
Swift 3 Wersja w przypadku, gdy ktoś po prostu chce skopiować & Wklej:
class TopAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
if let attrs = super.layoutAttributesForElements(in: rect) {
var baseline: CGFloat = -2
var sameLineElements = [UICollectionViewLayoutAttributes]()
for element in attrs {
if element.representedElementCategory == .cell {
let frame = element.frame
let centerY = frame.midY
if abs(centerY - baseline) > 1 {
baseline = centerY
alignToTopForSameLineElements(sameLineElements: sameLineElements)
sameLineElements.removeAll()
}
sameLineElements.append(element)
}
}
alignToTopForSameLineElements(sameLineElements: sameLineElements) // align one more time for the last line
return attrs
}
return nil
}
private func alignToTopForSameLineElements(sameLineElements: [UICollectionViewLayoutAttributes]) {
if sameLineElements.count < 1 { return }
let sorted = sameLineElements.sorted { (obj1: UICollectionViewLayoutAttributes, obj2: UICollectionViewLayoutAttributes) -> Bool in
let height1 = obj1.frame.size.height
let height2 = obj2.frame.size.height
let delta = height1 - height2
return delta <= 0
}
if let tallest = sorted.last {
for obj in sameLineElements {
obj.frame = obj.frame.offsetBy(dx: 0, dy: tallest.frame.origin.y - obj.frame.origin.y)
}
}
}
}
@ DongXu's answer jest poprawne. Sugeruję jednak wykonanie tych obliczeń w metodzie UICollectionViewFlowLayout
. Zapobiegnie to wielokrotnym obliczeniom na tych samych komórkach. Ponadto, prepare()
jest lepszym miejscem do zarządzania pamięcią podręczną atrybutów.
Użyłem czegoś podobnego do poprzednich odpowiedzi. W moim przypadku chcę wyrównać komórki przez kolumnę o różnych wysokościach.
import UIKit
class AlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
if let attributes = super.layoutAttributesForElements(in: rect) {
let sectionElements: [Int : [UICollectionViewLayoutAttributes]] = attributes
.filter {
return $0.representedElementCategory == .cell //take cells only
}.groupBy {
return $0.indexPath.section //group attributes by section
}
sectionElements.forEach { (section, elements) in
//get suplementary view (header) to align each section
let suplementaryView = attributes.first {
return $0.representedElementCategory == .supplementaryView && $0.indexPath.section == section
}
//call align method
alignToTopSameSectionElements(elements, with: suplementaryView)
}
return attributes
}
return super.layoutAttributesForElements(in: rect)
}
private func alignToTopSameSectionElements(_ elements: [UICollectionViewLayoutAttributes], with suplementaryView: UICollectionViewLayoutAttributes?) {
//group attributes by colum
let columElements: [Int : [UICollectionViewLayoutAttributes]] = elements.groupBy {
return Int($0.frame.midX)
}
columElements.enumerated().forEach { (columIndex, object) in
let columElement = object.value.sorted {
return $0.indexPath < $1.indexPath
}
columElement.enumerated().forEach { (index, element) in
var frame = element.frame
if columIndex == 0 {
frame.origin.x = minimumLineSpacing
}
switch index {
case 0:
if let suplementaryView = suplementaryView {
frame.origin.y = suplementaryView.frame.maxY
}
default:
let beforeElement = columElement[index-1]
frame.origin.y = beforeElement.frame.maxY + minimumInteritemSpacing
}
element.frame = frame
}
}
}
}
public extension Array {
func groupBy <U> (groupingFunction group: (Element) -> U) -> [U: Array] {
var result = [U: Array]()
for item in self {
let groupKey = group(item)
if result.has(groupKey) {
result[groupKey]! += [item]
} else {
result[groupKey] = [item]
}
}
return result
}
}
Wynika to z tego układu:
- 1. Wyrównanie w pionie tekstu w UILabel
- 2. wyrównanie w pionie tekstu w wierszu NSTableView
- 3. Wyrównanie tekstu w pionie w WPF TextBlock
- 4. Widok UICollection Dopasuj rozmiar komórki do rozmiaru ekranu
- 5. Wyrównanie w pionie za pomocą CSS
- 6. Wyrównanie w pionie tekstu i wiadomości Hyphend
- 7. Tekst na przycisku w pionie wyrównanie
- 8. Jak utworzyć układ Tiling/układ przepływu w TkInter?
- 9. UICollection Odległość między komórkami?
- 10. Widok obracania Monotouch w pionie/poziomie krajobrazu
- 11. Widok zend: bootstrap (widok) lub bootstrap (układ)
- 12. Wyrównanie w pionie zawartości w elementach listy blokowanych w linii
- 13. Bootstrap, jak uzyskać wyrównanie w pionie tekstu w pojemniku div
- 14. Układ widok po zmianie rozmiaru
- 15. Wyrównanie w pionie - IE10 Flex box nie działa
- 16. jonowe 2 wyrównanie w pionie za pomocą jonów siatki
- 17. Android: wyrównanie w pionie dla wielu linii EditText (obszar tekstu)
- 18. iOS 7 Przycisk strzałki wstecz Wyrównanie w pionie
- 19. Wyrównanie w pionie z modelem flex z przepełnieniem auto
- 20. Jak dodać widok recyklingu w układ xml
- 21. Jak przewinąć układ tabeli w poziomie i pionie w Androidzie
- 22. Wyrównanie w pionie tekstu w widoku tekstowym za pomocą złożonego rysunku
- 23. Układ systemu Android zastępujący widok innym widokiem w czasie wykonywania.
- 24. Jak zrobić układ liniowy dodać widok podrzędny w nowej linii?
- 25. Wyrównanie nie tuż przy dodawaniu widok dynamicznie GridLayout
- 26. Wyrównanie w pionie obrazu w div jednostki nadrzędnej za pomocą css
- 27. Czy możliwe jest usunięcie obrazów w UITabBarItem i wyrównanie w pionie tytułu
- 28. Poprawne wyrównanie TextViews w RelativeLayout
- 29. div pionowe wyrównanie środkowe css
- 30. Zmiana rozmiaru okna w pionie
co wyrównanie/konstrukcja chcesz ?? –
Wyrównanie dolne (wzdłuż czerwonej linii). Ale na dole lub na górze, to nie jest ważne, sposób na zrobienie tego powinien być taki sam, prawda? –