Published on

๐Ÿ“ฑ iOS - CompositionalLayout.02

Authors
  • avatar
    Name
    ์ด์ฐฝ์ค€
    Twitter

Supplementary Item

CollectionView๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋ฉด ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š” ์š”์†Œ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Badges, Headers, Footers๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์ด๊ฒƒ๋“ค์€ ๋ฆฌ์ŠคํŠธ์˜ ์•ž์ด๋‚˜ ๋’ค์— ๋ถ™์–ด ์ „์ฒด์ ์ธ ๋ฆฌ์ŠคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค.

Badges

CompositionalLayout์—์„œ๋Š” ์ด๋Ÿฐ SupplementaryItem๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋”์šฑ ์‰ฝ๊ฒŒ Anchor ๊ฐœ๋…์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค.

SupplementaryItem๊ณผ CollectionView์˜ ์‹œ๊ฐ์ ์ธ ๊ด€๊ณ„๋กœ์„œ ์ด๋“ค์˜ ์œ„์น˜๋ฅผ ์ •ํ•ด์ค€๋‹ค๋Š” ๊ฐœ๋…์ž…๋‹ˆ๋‹ค.

๊ฐœ๋… ์ž์ฒด๋„ ๊ต‰์žฅํžˆ ์‰ฝ์ฃ ?

์ ์šฉ๋„ ๋™์ผํ•˜๊ฒŒ ๋งค์šฐ ์‰ฝ๊ฒŒ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

let badgeAnchor = NSCollectionLayoutAnchor(
	edges: [.top, .trailing],
	fractionalOffset: CGPoint(x: 0.3, y: -0.3)
)
let badgeSize = NSCollectionLayoutSize(
	widthDimension: .absolute(20),
	heightDimension: .absolute(20)
)
let badge = NSCollectionLayoutSupplementaryItem(
	layoutSize: badgeSize,
	elementKind: "badge",
	containerAnchor: badgeAnchor
)
let item = NSCollectionLayoutItem(
	layoutSize: itemSize,
	supplementaryItems: [badge]
)

์—ฌ๊ธฐ์„œ ์ ์šฉ๋œ badge๋ผ๋Š” Item์€ ์šฐ์ธก ์ƒ๋‹จ์— ์œ„์น˜ํ•˜๊ณ  20x20์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ–๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์ฃ .

Header์™€ Footer๋Š” Badges์™€๋Š” ๋‹ค๋ฅธ ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Badges๋Š” Item์˜ ํŠน์ • ์œ„์น˜์— ๊ฒน์ณ๋ณด์ด๋Š” ์š”์†Œ์ง€๋งŒ, Header์™€ Footer๋Š” Item์„ ๋ฐ€์–ด๋‚ด๊ณ  ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๋ฉด์„œ ์œ„์น˜ํ•˜๋Š” ์š”์†Œ๋ผ๋Š” ์ ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ Header์™€ Footer๋Š” Boundary๋ผ๋Š” ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

let header = NSCollectionLayoutBoundarySupplementaryItem(
	contentSize: headerSize,
	elementKind: "header",
	alignment: .top
)
let footer = NSCollectionLayoutBoundarySupplementaryItem(
	layoutSize: footerSize,
	elementKind: "footer",
	alignment: .bottom
)

header.pinToVisibleBounds = true
section.boundarySupplementaryItems = [header, footer]

pinToVisibleBounds ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•ด ํ”ํžˆ ๋งํ•˜๋Š” Sticky Header ๋˜ํ•œ ๋งŒ๋“ค๊ธฐ ์‰ฌ์›Œ์กŒ์Šต๋‹ˆ๋‹ค.

DecorationView

ScrollView๋“ค์˜ ๋ฐฐ๊ฒฝ์„ ๊พธ๋ฉฐ์ฃผ๋Š” DecorationView ๋˜ํ•œ ์•„๋ž˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

let background = NSCollectionLayoutDecorationItem.backgorund(elementKind: "background")
section.backgroundItems = [background]

layout.register(
	MyCoolDecorationView.self,
	forDecorationViewOfKind: "background"
)

Estimated Self-Sizing

Item๋“ค์˜ ์š”์†Œ๋“ค์˜ ํฌ๊ธฐ๊ฐ€ ์ •ํ•ด์ง€์ง€ ์•Š๊ณ  ๋ณ€ํ™”ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปจํ…์ธ ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„์ˆ˜๋„ ์žˆ๊ณ , OS์˜ ํ…์ŠคํŠธ ํฌ๊ธฐ๋ฅผ ๋ณ€๊ฒฝํ•จ์— ๋”ฐ๋ผ size์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธธ์ˆ˜๋„ ์žˆ์ฃ .

size๋ฅผ ์„ค์ •ํ•ด์ค„ ๋•Œ .estimated์„ ํ™œ์šฉํ•˜๋ฉด ์ด์— ๋Œ€ํ•ด ์œ ์—ฐํ•œ ๋Œ€์‘์ด ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

let headerSize = NSCollectionLayoutSize(
	widthDimension: .fractionalWidth(1.0),
	heightDimension: .estimated(44.0)
)
let header = NSCollectionLayoutBoundarySupplementaryitem(
	layoutSize: headerSize,
	elementKind: "header",
	alignment: .top
)
header.pinToVisibleBounds = true
section.boundarySupplementaryItems = [header, footer]

์œ„ ์˜ˆ์‹œ์˜ ๊ฒฝ์šฐ Item์˜ ๋†’์ด๋ฅผ ์ปจํ…์ธ ์˜ ํฌ๊ธฐ ๋ณ€ํ™”์— ๋Œ€์‘์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด์ฃ .

Group ์•ˆ์— Group ๋„ฃ๊ธฐ

CollectionView๊ฐ€ ๋ณต์žกํ•ด์ง€๋ฉด์„œ Group ์•ˆ์— ๋‹ค๋ฅธ Group์„ ๋„ฃ์„ ์ผ์ด ์ƒ๊ธธ ์ˆ˜๋„ ์žˆ๊ฒ ์ฃ .

์‚ฌ์‹ค NSCollectionLayoutGroup์€ NSCollectionLayoutItem์„ ์ƒ์†๋ฐ›์€ ํ•˜์œ„ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๋ง๋กœ, Group์„ ๋ชจ์•„์„œ ๋‹ค๋ฅธ Group์„ ๋งŒ๋“ค์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ฃ .

์ด๋Ÿฐ Nesting์—๋Š” ์ œํ•œ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ƒ๋‹นํžˆ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ์˜ ๋””์ž์ธ๋“ค์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ํ˜•ํƒœ๋ฅผ ๋งŒ๋“œ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค๋ฉด ๋ ๊นŒ์š”?

let leadingItem = NSCollectionLayoutItem(
	layoutSize: leadingItemSize
)
let trailingItem = NSCollectionLayoutItem(
	layoutSize: trailingItemSize
)
let trailingGroup = NSCollectionLayoutGroup.vertical(
	layoutSize: trailingGroupSize,
	subitem: trailingItem,
	count: 2
)
let containerGroup = NSCollectionLayoutGroup.horizontal(
	layoutSize: containerGroupSize,
	subitems: [leadingItem, trailingGroup]
)

์‚ฌ์‹ค ๊ต‰์žฅํžˆ ์ง๊ด€์ ์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

leadingItem๊ณผ trailingItem ๋‘˜์ด ๋ฌถ์ธ trailingGroup์„ containerGroup์œผ๋กœ ๋ฌถ์€ ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

CollectionView๋ฅผ CollectionView์— ๋„ฃ๊ธฐ

CollectionView ์•ˆ์— ๋˜ ๋‹ค๋ฅธ CollectionView๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ, ์Šคํฌ๋กคํ•˜๋Š” ๋ฐฉํ–ฅ์ด ๋ฐ”๋€Œ๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€์ž์—ฐ์Šค๋Ÿฌ์šด ๋™์ž‘์„ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”

section.orthogonalScrollingBehavior = .continuous

์ด ํ•œ ์ค„์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

enum UICollectionLayoutSectionOrthogonalScrollingBehavior: Int {
	case none
	case continuous
	case continuousGroupLeadingBoundary
	case paging
	case groupPaging
	case groupPagingCentered
}

์ด๋ ‡๊ฒŒ ๋‘๊ฐœ์˜ continuous ์˜ต์…˜๊ณผ 3๊ฐœ์˜ paging ์˜ต์…˜์ด ์žˆ์œผ๋‹ˆ ์›ํ•˜๋Š” ๊ฐ’์„ ์ฐพ์•„ ๋„ฃ์–ด๋ด…์‹œ๋‹ค.