티스토리 뷰

공부

FlexLayout 사용해보기

Zedd0202 2021. 5. 2. 10:35
반응형

 

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

오늘은 PinLayout 사용해보기에 이어서..PinLayout의 친구인 FlexLayout에 대해서 공부해보겠습니다!

 

# FlexLayout

- UIStackView를 개선한 Layout 프레임워크

- UIStackView보다 사용하기 간단 / 다양한 API

- 높은 성능  UIStackViews보다 8 ~ 12배 빠름.

- PinLayout과 같이 개발되었으므로 PinLayout과 유사한 구문과 메소드.

- 보통 PinLayout과 같이 사용된다. 

 

# PinLayout과의 차이점?

PinLayout도 Layout 프레임워크였는데..FlexLayout는 뭐가 다르냐!

많은 View를 레이아웃 해야 하지만, 복잡한 애니메이션이 필요하지 않은 상황에서는 FlexLayout이 적합하다. 

 

# 설치 

installation 참고

 

# 사용해보기 

FlexLayout를 사용하는 단계는 2단계로 나뉘어짐.

1. Container를 setup한다.

2. Container를 Layout한다.

 

1. Container를 setup한다.

import FlexLayout

let rootFlexContainer: UIView = UIView()

init() {
  self.view.addSubView(self.rootFlexContainer)
  
  self.rootFlexContainer.flex.define { (flex) in
  
  }
}

1) flexbox 가장 바깥쪽 Container를 만들고 addSubview한다.

2) flexbox구조 정의(define)를 한다. define closure안에서 내가 만들 flexbox를 구조화 하면 된다.

예를들어 이런식이다.

import FlexLayout

self.rootFlexContainer.flex.define { (flex) in
            
   flex.addItem(self.label)
   flex.addItem(self.label2)
   flex.addItem(self.label3)
}

 

2. Container를 Layout한다.

저러고 끝나는게 아니라, layoutSubviews()나 viewDidLayoutSubviews()에서 

1) flexbox container를 Layout한다.

2) flex 메소드인 layout()을 사용하여 flexbox child를 layout한다.

코드로 보면

import PinLayout
import FlexLayout

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        self.rootFlexContainer.pin.all() // 1)
        self.rootFlexContainer.flex.layout() // 2)
}

이런식이다. PinLayout의 pin을 이용해 container의 Layout을 먼저 잡아 준 뒤, child의 layout을 잡아준다.

FlexLayout을 사용한다면 거의 이런식으로 사용하게 될 것.

 

위 코드를 빌드하면

이런식으로 Layout이 잡히게 된다. 

 

# Flexbox를 Define할 때..많이 쓰이는 것들?!

self.rootFlexContainer.flex.define { }

지금은 이런식으로 바로 define을 호출했지만, 여기서 이런저런 설정들을 할 수 있다.

 

[direction]

self.rootFlexContainer.flex.direction(.column).define { }
or
self.rootFlexContainer.flex.direction(.row).define { }

direction은 StackViews의 main axis를 결정하는 메소드라고 보면 된다.

기본적으로 direction이 column으로 설정되어있으므로, 만약 main axis가 column이라면

self.rootFlexContainer.flex.define { }

그냥 이렇게만 해도 되는 것이다.

 

[padding]

self.rootFlexContainer.flex.padding(12).define { }

이렇게 padding도 줄 수 있다. 

viewDidLayoutSubviews에서 container를 layout할 때 줘도 되지만...이렇게 container 구조를 정의하는데서 주면 편리하다.

Padding을 넣게 되면

패딩 안넣은거 / 넣은거

오른쪽 그림처럼 모든 방향에 Padding이 들어가게 된다.

 

[paddingTop, left, right, bottom]

padding()은 모든 방향이지만, 이렇게 방향을 지정해줄 수도 있다.

self.rootFlexContainer.flex.paddingTop(12).define { }

 

[paddingHorizontal, paddingHorizontal]

paddingHorizontal : left, right, start, end padding을 넣음

paddingVertical : top bottom padding을 넣음

ex.

self.rootFlexContainer.flex.paddingVertical(20).define { }

 

[backgroundColor]

self.rootFlexContainer.flex.backgroundColor(.gray)

backgroundColor도 flex에서 바로 지정이 가능하다.

패딩을 안넣어서 다시 이렇게 됨

 

[grow]

self.rootFlexContainer.flex.grow(1).define { }

flex item이 grow(성장)하는 기능을 정의한다. 

item이 차지해야하는 flex container 내부의 사용가능한 공간을 나타낸다.

기본값은 0으로, view의 크기를 main-axis direction으로 유지한다. 

ex. 모든 항목이 1로 설정되면 모든 child item이 container내부에서 동일한 크기로 설정된다.

child 중 한명에게 2의 값을 주면, 그 child는 다른 child보다 2배의 공간을 차지하게 된다.

 

말로 하면 잘 이해가 안갈 수 있는데, 코드로 예를 들어보자.

현재 코드는

self.rootFlexContainer.flex.define { (flex) in
            
    flex.addItem(self.label)
    flex.addItem(self.label2)
}

self.rootFlexContainer.pin.all()
self.rootFlexContainer.flex.layout()

이렇게 되어있다.

만약 grow를 flex item에 사용하게 되면,

self.rootFlexContainer.flex.define { (flex) in
            
    flex.addItem(self.label).grow(1) ✅
    flex.addItem(self.label2).grow(1) ✅
} 

self.rootFlexContainer.pin.all()
self.rootFlexContainer.flex.layout()

이렇게 item이 grow(?..)되게 된다.

grow값을 다르게 줘보자.

self.rootFlexContainer.flex.define { (flex) in
            
    flex.addItem(self.label).grow(1)
    flex.addItem(self.label2).grow(2) ✅
}

self.rootFlexContainer.pin.all()
self.rootFlexContainer.flex.layout()

두번째 Label은 첫번째 Label보다 2배의 공간을 차지하게 된다.

 

[justifyContent]

flex container의 main-axis에 따라 정렬을 정의하는 프로퍼티이다.

기본값은 justifyContent(.start) 이다. 

어떤식으로 동작하는지 보고싶으면 문서를 참고하면 된다.


문서에 나와있는 FlexLayout Introduction examples를 이해하기 위한 프로퍼티와 메소드는 다 봤다. 

마지막으로 child layout을 결정하는 layout()메소드만 보면 될 것 같다.

 

# layout()

self.rootFlexContainer.flex.layout()

위에서도 말했지만, 이 layout은 flex container child를 layout하는 메소드이다.

 

위 코드에서는 단순히 layout()으로 되어있지만, 사실 위 코드는

self.rootFlexContainer.flex.layout(mode: .fitContainer)

mode가 fitContainer로 지정되어있는 것이다. (fitContainer가 기본값이라는 뜻)

mode는 총 3가지로 

- fitContainer - 기본값. child는 container의 크기(width, height)내에 배치된다.

- adjustHeight - child는 container의 너비만 사용하여 layout된다. container의 높이는 flexbox의 child에 맞게 조정된다.

- adjustWidth - child는 container의 높이만 사용하여 layout된다. container의 너비는 flexbox의 child에 맞게 조정된다.

가 있다. 

 

예를 들어보자. 현재 container가 

이렇게 view를 꽉채우고 있는데, 

self.rootFlexContainer.pin.all()

이 코드 때문에 당연하다. 

여기서

self.rootFlexContainer.pin.all()
self.rootFlexContainer.flex.layout(mode: .adjustHeight)

이렇게 mode를 adjustHeight으로 바꿔주면,

adjustHeight - child는 container의 너비만 사용하여 layout된다. container의 높이는 flexbox의 child에 맞게 조정된다.

adjustHeight의 정의대로 container의 높이는 child에 맞게 조정된 것을 볼 수 있다. 

 

대충 이정도면 FlexLayout을 사용하여 복잡한..StackView를 간단히 만들 수 있을 것 같다!!

 

참고

github.com/layoutBox/FlexLayout

반응형

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

FlexLayout (2)  (0) 2021.05.05
앱 종료하기 with animation  (2) 2021.05.04
extension Reactive  (1) 2021.04.28
PinLayout 사용해보기  (0) 2021.04.21
Carthage 사용해보기  (0) 2021.04.17