UICollectionViewDelegateFlowLayout 활용 Cell크기 동적 할당

2024. 4. 15. 11:50· 🍎swift
목차
  1. 공식문서
  2. 해결해보자
  3. 1트
  4. 2트
  5. 결과 …
  6. 3트.. 해결

cell의 넓이는 고정값으로 줄 수 있지만 높이는 내용에 따라 동적으로 할당 받아야하는데 어떻게 해야할지 뒤적뒤적이다 UICollectionViewDelegateFlowLayout라는 protocol이 있다는 것을 발견

요놈을 활용해 동적 높이를 할당해보자 

공식문서

UICollectionViewDelegateFlowLayout

The methods that let you coordinate with a flow layout object to implement a grid-based layout.

The methods of this protocol define the size of items and the spacing between items in the grid.

공식문서를 요약하면 이렇게 나온다.

즉 아이템과 grid사이의 size와 spacing 조절해주는 protocol이런건데 이걸 보고 딱 감이왔다 아 이놈이네?

여담이지만 공부하다보니 이 프로토콜을 사용하여 셀의 크기, 헤더와 푸터의 크기, 섹션간 간격 등을 지정할 수 있다고 한다.

해결해보자

메서드들의 쓰임세를 정리하면 아래와 같다.

  • 셀 크기 조정: sizeForItemAt 셀의 크기를 지정
  • 섹션 패딩 조정: insetForSectionAt  섹션의 내부 여백을 설정
  • 행 간의 간격 지정: minimumLineSpacingForSectionAt 
  • 아이템 간의 간격 지정: minimumInteritemSpacingForSectionAt

1트

나는 셀 크기를 동적으로 지정해줘야하니 sizeForItemAt를 사용해서 임시로 아래와 같이 만들어줬다.

extension DetailChatViewController: UICollectionViewDelegateFlowLayout {
   func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let message = viewModel.messageRepository.getMessages()[indexPath.row].content
        return CGSize(width: collectionView.frame.width, height: 100)
        }
}

처음 코드를 보고 오 쉽네 ? 그냥 데이터 내용을 height에 넣고 리턴해주면 되는건가라고 생각 할 수 있지만

height 100이 넘어가지 안는 내에서 만 작동을 하게 된다. 

즉 sizeToFit()를 사용할때처럼 크기를  딱 맞춰서 동적인 UI를 적용하고 싶었다.

retrun타입을 보니 CGSize, message를 CGFloat타입으로 만들어버리면 끝이구만

2트

boundingRect(with:options:attributes:context:)라는 메서드는 문자열에 대해 지정된 속성을 사용하여 그 텍스트가 차지할 최소 영역을 계산하고 그 결과를 CGRect로 반환하는 메서드이다. 즉 문자열의 구성을 보고  크기가 얼마인지 정확하게 계산해 retrun을 해주는 메서드, 이것을 활용해 texrtView에서 나오는 text들의 크기를 측정하고 반환하도록 했다.

  1. boundingRect() 를 사용하기 위해 CGSize가 필요하다.
  2. height는 greatestFiniteMagnitude**를이용해서 무한대로 조정
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            let message = viewModel.messageRepository.getMessages()[indexPath.row].content
            let maxWidth = collectionView.frame.width - 20
            let textSize = CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude)

            let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15)]
            let estimatedFrame = NSString(string: message).boundingRect(with: textSize, options: .usesLineFragmentOrigin, attributes: nil, context: nil)

            return CGSize(width: collectionView.frame.width, height: ceil(estimatedFrame.height) + 20) // 추가 마진
        }

결과 …

작동은 잘 되지만 …..

??? 어마무지한 Autolayout충돌이 되는 모습을 보여준다 ..

3트.. 해결

두번째 시도에서 attributes에 nil을 넣어줬던 것이 실수였다.

UICollectionViewLayout에서 attributes역할은

  1. 폰트 스타일: 텍스트의 폰트 종류와 크기를 지정 예를 들어, **UIFont.systemFont(ofSize: 15)**는 시스템 폰트로 15포인트 크기를 사용
  2. 텍스트 색상: **NSAttributedString.Key.foregroundColor**를 사용하여 텍스트의 색상을 지정
  3. 밑줄: NSAttributedString.Key.underlineStyle을 사용하여 텍스트에 밑줄을 추가
  4. 텍스트 정렬: NSAttributedString.Key.paragraphStyle를 사용하여 텍스트의 정렬(왼쪽, 가운데, 오른쪽)을 설정 가능.
  5. 배경 색상: NSAttributedString.Key.backgroundColor를 사용하여 텍스트의 배경 색상을 지정
  6. 삭제선: NSAttributedString.Key.strikethroughStyle을 사용하여 텍스트에 삭제선을 추가 가능
  7. 커스텀 속성: 개발자가 정의한 커스텀 속성을 텍스트에 적용할 가능

이러한 역할을 갖고 있다고 한다.

<예제코드>

let attributes: [NSAttributedString.Key: Any] = [
    .font: UIFont.boldSystemFont(ofSize: 16),
    .foregroundColor: UIColor.blue,
    .backgroundColor: UIColor.yellow,
    .underlineStyle: NSUnderlineStyle.single.rawValue
]
let attributedString = NSAttributedString(string: "Hello, world!", attributes: attributes)

두번째 코드에서 attributes를 추가해주고 width를 collectionView크기로 맞춰줘 통일감을 주었다..

   
   //두번째 코드 
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
     let message = viewModel.messageRepository.getMessages()[indexPath.row].content
     let maxWidth = collectionView.frame.width - 20
     let textSize = CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude)
     let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15)]
     let estimatedFrame = NSString(string: message).boundingRect(with: textSize, options: .usesLineFragmentOrigin, attributes: nil, context: nil)
     return CGSize(width: collectionView.frame.width, height: ceil(estimatedFrame.height) + 20) // 추가 마진
}

//리팩토링 코드 (해결코드)
extension DetailChatViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
          let message = viewModel.messageRepository.getMessages()[indexPath.row].content
          let width = collectionView.frame.width
          let size = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
          let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15)]
          let estimatedFrame = NSString(string: message).boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
          return CGSize(width: width, height: estimatedFrame.height + 20)
      }
}

잘 돌아간다 ! 완료 !!  

'🍎swift' 카테고리의 다른 글

swift indicator 구현  (0) 2024.04.15
Swift 배열, 동시성 문제  (0) 2024.04.04
URLRequestBuilder만들기 .. feat 리팩토링  (0) 2024.04.02
TLI - Concurrency  (0) 2024.01.17
[Swift] Stroyboard Navigation Controller를 활용한 화면이동  (1) 2023.12.21
  1. 공식문서
  2. 해결해보자
  3. 1트
  4. 2트
  5. 결과 …
  6. 3트.. 해결
'🍎swift' 카테고리의 다른 글
  • swift indicator 구현
  • Swift 배열, 동시성 문제
  • URLRequestBuilder만들기 .. feat 리팩토링
  • TLI - Concurrency
Kendrick
Kendrick
권군 개발일기장Kendrick 님의 블로그입니다.
Kendrick
권군 개발일기장
Kendrick
전체
오늘
어제
  • 분류 전체보기 (27)
    • 💻CS (0)
    • 📝코딩테스트 (2)
    • 🍎swift (21)
      • swift 기초 (2)
      • Apple공식문서 번역 및 요약 (1)
      • [Playground]코딩배우기2 (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • swfit
  • restfull
  • 고차함수
  • 코딩배우기2
  • 클로저활용
  • 동시성
  • urlsession
  • 전치연산자
  • 제네릭
  • UICollectionViewDelegateFlowLayout
  • 강한참조사이클
  • API
  • 메모리관리
  • playground
  • navigationController
  • ViewController
  • 메서드
  • 메모리누수
  • Indicator
  • 코딩테스트
  • 타입메서드
  • 에러처리
  • 연산자커스텀
  • storyboard
  • 배열
  • 문자열
  • Result타입
  • closure
  • Swift
  • 후치연산자

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
Kendrick
UICollectionViewDelegateFlowLayout 활용 Cell크기 동적 할당
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.