iOS/Swift

[Swift] UICollectionView์—์„œ Cell์„ ์™ผ์ชฝ ์ •๋ ฌ(Left Alignment) ํ•˜๋Š” ๋ฐฉ๋ฒ•

๊ฒฝํ‘ธ 2022. 2. 14. 17:27
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š”~

 

์˜ค๋Š˜์€ CollectionView์—์„œ ์…€๋“ค์„ ์™ผ์ชฝ์ •๋ ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๋‹ค๊ฐ€ 

๊ดœ์ฐฎ์€ ๋ฐฉ๋ฒ•์ด ์žˆ์–ด ์ •๋ฆฌํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 


๋จผ์ € ์‚ฌ์šฉํ•˜๊ฒŒ ๋ 

UICollectionViewFlowLayout์— ๋Œ€ํ•ด์„œ ๊ฐ„๋žตํžˆ ์†Œ๊ฐœํ•˜๊ณ  ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

FlowLayout

  • UICollectionViewFlowLayout ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ์…€์„ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ์ •๋ ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • FlowLayout์€ ๋ ˆ์ด์•„์›ƒ ๊ฐ์ฒด๊ฐ€ ์…€์„ ์„ ํ˜• ๊ฒฝ๋กœ์— ๋ฐฐ์น˜ํ•˜๊ณ  ์ตœ๋Œ€ํ•œ ๋งŽ์€ ์…€์„ ์ฑ„์šฐ๋Š” ๊ฒƒ์„ ๋งํ•ฉ๋‹ˆ๋‹ค.
  • ํ˜„์žฌ ํ–‰์—์„œ ๋ ˆ์ด์•„์›ƒ ๊ฐ์ฒด์˜ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•˜๋ฉด ์ƒˆ๋กœ์šด ํ–‰์„ ์ƒ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์—ญํ• 

  • ํ”Œ๋กœ์šฐ ๋ ˆ์ด์•„์›ƒ ๊ฐ์ฒด๋ฅผ ์ž‘์„ฑํ•ด ์ปฌ๋ ‰์…˜๋ทฐ์˜ ๋ ˆ์ด์•„์›ƒ ๊ฐ์ฒด๋กœ ์ง€์ •
  • ์…€์˜ ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ๊ตฌ์„ฑ
  • ์…€์˜ ๊ฐ„๊ฒฉ์„ ์กฐ์ ˆ
  • ์„น์…˜์˜ ํ—ค๋” ํ˜น์€ ์„น์…˜ ํ‘ธํ„ฐ๋ฅผ ํฌ๊ธฐ๋ฅผ ์ง€์ •
  • ์Šคํฌ๋กค ๋ฐฉํ–ฅ์„ ์„ค์ •

์†์„ฑ

์•„๋ž˜์˜ ์ด๋ฏธ์ง€๋ฅผ ๋ณด๋ฉด Attributes๋Š” ์ด 5๊ฐ€์ง€์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด

์…€, ํ—ค๋”, ํ‘ธํ„ฐ์˜ ๋„ˆ๋น„, ๋†’์ด, ๊ฐ„๊ฒฉ ๋“ฑ์„ ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์™ผ์ชฝ ์ •๋ ฌ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ฒซ ๋ฒˆ์งธ ๋ฉ”์„œ๋“œ์ธ ForElements๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋งŒ์•ฝ ์•„์ดํ…œ๋ณ„๋กœ ์‚ฌ์ด์ฆˆ๋ฅผ ์กฐ์ ˆํ•˜๊ฑฐ๋‚˜ ๊ฐ„๊ฒฉ ๋“ฑ์„ ์กฐ์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ForItem์„ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋˜๊ณ 

ํ—ค๋” ํ˜น์€ ํ‘ธํ„ฐ๋ฅผ ์กฐ์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด SupplementaryView๋ฅผ

์ปฌ๋ ‰์…˜๋ทฐ์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋ทฐ๋ฅผ ์กฐ์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด DecorationView๋ฅผ ํ™œ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๋‚˜์ค‘์— ๊ธฐํšŒ๊ฐ€ ๋œ๋‹ค๋ฉด ๋‚˜๋จธ์ง€ ๋ฉ”์„œ๋“œ์™€ ์ปฌ๋ ‰์…˜๋ทฐ์— ๋Œ€ํ•ด ์ž์„ธํ•œ ๋‚ด์šฉ์„ ํฌ์ŠคํŒ…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค : - )

๋ฐฉ๋ฒ•

ํ”Œ๋กœ์šฐ ๋ ˆ์ด์•„์›ƒ ๊ฐ์ฒด๋ฅผ ํ•˜๋‚˜๋ฅผ ๋งŒ๋“ค๊ณ , ์•ž์„œ ๋งํ•œ ForElements ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

// Left Aligned
class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect)
        
        var leftMargin = sectionInset.left
        var maxY: CGFloat = -1.0
        attributes?.forEach { layoutAttribute in
            if layoutAttribute.representedElementKind == nil {
                if layoutAttribute.frame.origin.y >= maxY {
                    leftMargin = sectionInset.left
                }
                
                layoutAttribute.frame.origin.x = leftMargin
                
                leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
                maxY = max(layoutAttribute.frame.maxY, maxY)
            }
        }
        return attributes
    }
}

์œ„์˜ ์ฝ”๋“œ๋Š” Cell์„ ์™ผ์ชฝ ์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•ด ForElement๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ฝ”๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

1. attributes๋ฅผ ์„ ์–ธํ•˜๊ณ  ํ•˜๊ณ  super ํด๋ž˜์Šค์˜ Attribute๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ต๋‹ˆ๋‹ค.

let attributes = super.layoutAttributesForElements(in: rect)


2. leftMargin์„ ์ดˆ๊ธฐ Section.left์œผ๋กœ ์ฃผ๋Š” ์ด์œ ๋Š” ์‹œ์ž‘์ ์„ ์„น์…˜์˜ ์™ผ์ชฝ ์ธ์…‹๊ณผ ๊ฐ™์€ ๊ฐ’์„ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค. ํ”„๋กœํผํ‹ฐ๋ฅผ ๋น„๊ตํ•ด ๊ฐ€๋ฉด์„œ ํ–‰์ด ๋ฐ”๋€Œ๋ฉด ๋‹ค์‹œ ๊ฐ™์€ ๊ฐ’์œผ๋กœ ๋Œ์•„์˜ค๊ฒŒ ๋˜์ฃ .

var leftMargin = sectionInset.left
if layoutAttribute.frame.origin.y >= maxY {
    leftMargin = sectionInset.left
}

 

3. maxY๋Š” 0 ์ดํ•˜์˜ ๊ฐ’์œผ๋กœ ์‹œ์ž‘ํ•ด ์…€์˜ ๊ฐ yํฌ์ง€์…˜์„ ๋น„๊ตํ•ด ๊ฐ€๋ฉด์„œ yํฌ์ง€์…˜์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ณ€์ˆ˜๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์…€์˜ ํ–‰์ด ๋‹ค์Œ์ธ์ง€ ์•„๋‹Œ์ง€ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด max ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋น„๊ตํ•˜๊ณ  ๋‹ค์Œ ํ–‰์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜๋Š” ์›๋ฆฌ์ž…๋‹ˆ๋‹ค.

var maxY: CGFloat = -1.0
maxY = max(layoutAttribute.frame.maxY, maxY)

 

4. leftMargin์„ ์ด์šฉํ•ด ๊ฐ ์…€์˜ xํฌ์ง€์…˜์„ ์ •ํ•ด์ฃผ๊ณ  ํ•ด๋‹น ์…€์˜ ๋„“์ด์™€ ๊ฐ„๊ฒฉ์„ ๋”ํ•ด๊ฐ€๋ฉด์„œ ๋‹ค์Œ ์œ„์น˜๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing

5. ์ ์šฉ

์ž‘์„ฑํ•œ FlowLayout์„ CollectionView์— ์ ์šฉํ•ด ์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

let collectionView: UICollectionView = {
        
        let layout = LeftAlignedCollectionViewFlowLayout()
        layout.minimumLineSpacing = 10
        layout.minimumInteritemSpacing = 10
        
        let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        
        return collectionView
}

 

์ •๋ฆฌ

 

์œ„ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ํ™•์ธํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์…€์ด ์™ผ์ชฝ ์ •๋ ฌ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

[ ๋‚ด๊ฐ€ ํ•˜๊ณ  ์‹ถ์€ ] ์„น์…˜์„ ๋ณด๋ฉด

[ ์ฝ”๋”ฉ ] , [ ์•™ํผํ‰์Šค! ] , [ ๊ฒŒ์ž„ ] ๊ทธ๋‹ค์Œ ์˜ค๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด [ ์Œ์ฃผ, ๊ฐ€๋ฌด, ๊ฒŒ์ž„ ]์ธ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

[ ์Œ์ฃผ, ๊ฐ€๋ฌด, ๊ฒŒ์ž„ ] ์…€์ด ์ฐจ์ง€ํ•˜๋Š” ๊ณต๊ฐ„์ด [ ๊ฒŒ์ž„ ] ๋’ค์— ์˜ฌ ์ˆ˜ ์—†๊ฒŒ ๋˜๋‹ˆ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋‹ค์Œ ํ–‰์œผ๋กœ ๋„˜์–ด๊ฐ€๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์•ž์„œ ์„ค๋ช…ํ–ˆ๋˜

"ํ˜„์žฌ ํ–‰์—์„œ ๋ ˆ์ด์•„์›ƒ ๊ฐ์ฒด์˜ ๊ณต๊ฐ„์ด ๋ถ€์กฑํ•˜๋ฉด ์ƒˆ๋กœ์šด ํ–‰์„ ์ƒ์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค."์™€ ๊ฐ™์€ ํŠน์„ฑ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

๊ฒฐ๊ณผ์ ์œผ๋กœ

์™ผ์ชฝ์˜ ๊ธฐ์ค€์ ์„ ๋งŒ๋“ค์–ด์ฃผ๊ณ  ์ฐจ๊ณก์ฐจ๊ณก ์Œ“์•„๊ฐ€๋‹ค

์…€์˜ ๊ธธ์ด๊ฐ€ ๋ ˆ์ด์•„์›ƒ์˜ ๋ฒ”์œ„๋ฅผ ์ดˆ๊ณผํ•œ๋‹ค๋ฉด ๋‹ค์Œํ–‰์œผ๋กœ

๋‹ค์‹œ ์™ผ์ชฝ ๊ธฐ์ค€์ ์„ ๋งŒ๋“ค์–ด ์œ„์˜ ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 


 

UICollectionView์˜ ์…€๋“ค์„ ์™ผ์ชฝ ์ •๋ ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž‘์„ฑํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.

์กฐ๊ธˆ ๋” ํŽธํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ๊ฑฐ๋‚˜ ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“ ์ง€ ๋Œ“๊ธ€ ๋‹ฌ์•„์ฃผ์„ธ์š”. 

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด๋งŒ ๐Ÿ‘‹๐Ÿป ๐Ÿ‘‹๐Ÿป ๐Ÿ‘‹๐Ÿป

๋ฐ˜์‘ํ˜•