AlignedCollectionViewFlowLayout icon indicating copy to clipboard operation
AlignedCollectionViewFlowLayout copied to clipboard

Vertical Aligment Bug

Open WessonWu opened this issue 7 years ago • 4 comments

    fileprivate func layoutAttributes(forItemsInLineWith layoutAttributes: UICollectionViewLayoutAttributes) -> [UICollectionViewLayoutAttributes] {
        guard let lineWidth = contentWidth else {
            return [layoutAttributes]
        }
        var lineFrame = layoutAttributes.frame
        lineFrame.origin.x = sectionInset.left
        lineFrame.size.width = lineWidth
        
        // Need to be add
        // bug fix for super.layoutAttributesForElements(in:)
        // if there are three row (Row1, Row2, Row3), and rows step by step closly, such as
        // Row1: (x: 0, y: 0, width: 375, 100)
        // Row2: (x: 0, y: 100, width: 375, height: 100)
        // Row3: (x: 0, y: 200, width: 375, height: 100)
        // then super.layoutAttributesForElements() will reture 3 values(Row1, Row2, Row3), that is incorrect
        if lineFrame.height > 2 {
            lineFrame.origin.y += 1
            lineFrame.size.height -= 2
        }
        
        return super.layoutAttributesForElements(in: lineFrame) ?? []
    }

WessonWu avatar Jun 23 '18 02:06 WessonWu

That's a good observation! Thanks for reporting this!

I hadn't noticed that it doesn't work with interitem / line spacings of 0. However, this is not the only place where the frame needs to be adjusted: More importantly, this function needs adjustment: fileprivate func isFrame(for firstItemAttributes: UICollectionViewLayoutAttributes, inSameLineAsFrameFor secondItemAttributes: UICollectionViewLayoutAttributes)

Furthermore, x += 1 and height -= 2 won't do it as it will also introduce inaccuracy. Retina screens support 0.5pt intervals, super retina displays 1/3pt intervals and there might be other resolutions in the future. Thus, I'll need to find a solution how to deal with that in a safe way.

Any suggestions are welcome! :)

mischa-hildebrand avatar Jun 23 '18 15:06 mischa-hildebrand

By the way: I think, it's a rounding bug because the documentation of the intersects(_:) function itself states:

The first rectangle intersects the second if the intersection of the rectangles is not equal to the null rectangle.

When I define two rectangles as follows:

let rect1 = CGRect(x: 0, y: 0, width: 100, height: 100)
let rect2 = CGRect(x: 0, y: 100, width: 100, height: 100)

the intersection of the rectangles is the null rectangle and thus

rect1.intersects(rect2)

returns false.

mischa-hildebrand avatar Jun 23 '18 16:06 mischa-hildebrand

ok, I got it, thank you for your reply and correct my thinking

WessonWu avatar Jun 23 '18 16:06 WessonWu

Hi! Is there any solution for this problem?

yojkim avatar Jul 01 '21 03:07 yojkim