티스토리 뷰

공부

FlexLayout (2)

Zedd0202 2021. 5. 5. 18:15
반응형

 

안녕하세요 :) Zedd입니다.

오늘은 FlexLayout 2탄!!!

막상 사용하려니 모르는 메소드가 너무 많아따

 

# Accessing flex item's UIView

add한 아이템의 속성을 바꾸고 싶으면 

view.flex.direction(.row).padding(20).alignItems(.center).define { (flex) in
        flex.addItem().width(50).height(50).define { (flex) in
            flex.view?.alpha = 0.8 ✅
        }
    }

define closure안에서 flex.view로 접근이 가능하다.

view.flex.direction(.row).padding(20).alignItems(.center).define { (flex) in
        let container = UIView()
        container.alpha = 0.8
        
        flex.addItem(container).width(50).height(50)
    }

물론 이런식으로 해도 ㄱㅊ

 

# markDirty()

제일 궁금했던거...더티로 표시(?)한다는게 무슨뜻..

FlexLayout은 고도로 최적화되었기 때문에

1. flex 프로퍼티가 변경
2. flex container 크기가 변경

될때만 flex item이 레이아웃됨.

FlexLayout이 flex item을 레이아웃 하도록 강제하려는 경우 markDirty()를 사용하면 됨.

Dirty 플래그는 flexbox tree의 루트로 전파되어 item이 invalidate되면 전체 하위 tree가 다시 계산되도록 한다.

예를 들어보자.

@IBAction func buttonDidTap(_ sender: Any) {
      self.label.text = "안녕안녕"
}

button을 누르면 label의 text를 바꾸도록 했다. 

하지만, 

label의 높이가 이전 text의 높이로 잡힌것을 볼 수 있다.

이럴 때 

1. Label을 dirty로 마크한 뒤

2. flex container에서 re-layout 하도록 강제하면 된다. 

@IBAction func buttonDidTap(_ sender: Any) {
        self.label.text = "안녕안녕"
        
        self.label.flex.markDirty() // 1
        self.rootFlexContainer.flex.layout() // 2
        or
        self.view.setNeedsLayout() // 2
}

이렇게 하면

이렇게 높이 변경이 잘 된다. 

 

# display

item 표시 여부 설정.

값이 none이면 item이 숨겨지고, 레이아웃에 포함되지 않는다.

예를 들어보자.

이렇게 Label들이 있고, 첫번째 Label을 숨기고 싶다면,

@IBAction func buttonDidTap(_ sender: Any) {        
        self.label.flex.display(.none) ✅
        
        self.rootFlexContainer.flex.layout()
    }

display를 none으로 주면 된다.

🧐 한가지 궁금증은..위에서 

FlexLayout은 고도로 최적화되었기 때문에
1. flex 프로퍼티가 변경
2. flex container 크기가 변경
될 때만 flex item이 레이아웃됨.

이라고 했는데, 

self.label.flex.display(.none) ✅

이게 flex 프로퍼티가 변경되는 것 아닌가..? 그래서 따로 layout을 강제안해도 괜찮을줄 알았는데..

self.rootFlexContainer.flex.layout()

를 호출안하면 label이 사라지지 않는다....

추측하건데, flex item. 즉 label에 대해서는 layout이 되었지만,

rootFlexContainer에 대해서는 layout이 안되어서...그대로 있는 것 같다..!?

 

# isIncludedInLayout

flexbox의 UIView가 flexbox레이아웃에 포함되는지 여부를 동적으로 제어한다.

flexbox의 UIView가 제외되면, FlexLayout은 해당 view와 subview를 레이아웃하지 않는다.

예를 들어보자.

이렇게 view를 구성했다.

makeDirty때 본 것 처럼

@IBAction func buttonDidTap(_ sender: Any) {
        self.label.text = "안녕"
        
        self.label.flex.markDirty()
        self.rootFlexContainer.flex.layout()
    }

레이아웃이 잘 잡힌다. 

저 Label을 isIncludedInLayout을 이용해 flexbox에서 제외하면

@IBAction func buttonDidTap(_ sender: Any) {
        self.label.flex.isIncludedInLayout = false ✅
        self.label.text = "안녕"
        
        self.label.flex.markDirty()
        self.rootFlexContainer.flex.layout()
    }

flexbox layout에서 제외된다.

 

# Absolute positioning

position(_: Position) 메소드를 이용하여 flexbox에 item을 상위 항목 내에 배치할 수 있다.

예를 들어보자. 

이렇게 Label을 절대 위치에 배치하고 싶으면 

flex.addItem(self.label2).position(.absolute).top(10).left(30).right(5)

position메소드를 이용하면 된다.

 

# shrink

문서에는 설명이 막 나와있는데..써도 모를 것 같아 그냥 예제로 보기로 하자.

빨간색 flexbox는 

flex.addItem().direction(.row).define { (flex) in
        flex.addItem(self.label2).width(50%)
        flex.addItem(self.label3).width(50%)
}

이렇게 width를 50%준 상태이다.

이를 shrink를 사용하여 바꿔보자. shrink는 축소하는 비율을 줄 수 있다.

flex.addItem(self.label2).shrink(1)
flex.addItem(self.label3).shrink(1)

이렇게 shrink를 똑같이 주면 당연히 

동일한 축소 비율을 가져가고,

flex.addItem(self.label2).shrink(2) ✅
flex.addItem(self.label3).shrink(1)

이렇게 label2에 대해 shrink를 2를 주면, 2/3만큼 "축소"한다는 거라고 보면 된다.

이런식..

 

# 이삭 줍기..

PinLayout 문서 보다가 ㅋㅋ..오타 발견해서 PR올렸더니..드디어 ㅁ ㅓ지가 됐네요...

이삭..맛있다...😂

 

참고

github.com/layoutBox/FlexLayout

반응형

'공부' 카테고리의 다른 글

Bundling Resources with a Swift Package  (1) 2021.05.15
Swift Package Resource - Copy와 Process의 차이점  (0) 2021.05.15
앱 종료하기 with animation  (2) 2021.05.04
FlexLayout 사용해보기  (4) 2021.05.02
extension Reactive  (1) 2021.04.28