ErrorNote, Flutter, RenderFlex children... 관련 에러

Uno·2024년 1월 7일
0

ErrorNote

목록 보기
5/6

Problem: 화면 랜더링 실패 (ScrollView + Column 사용)

상황에 따라 조금씩 에러메시지는 다를 수 있겠으나, 내가 만난 에러는 다음과 같다.

RenderFlex children have non-zero flex but incoming height constraints are unbounded.
When a column is in a parent that does not provide a finite height constraint, for example if it is in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining space in the vertical direction.
These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child cannot simultaneously expand to fit its parent.
Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible children (using Flexible rather than Expanded). This will allow the flexible children to size themselves to less than the infinite remaining space they would otherwise be forced to take, and then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum constraints provided by the parent.

코드를 간략히 표현하면 다음과 같다.

WriteDiaryPage
 └─ Scaffold
    ├─ AppBar
    │  └─ BackButton
    └─ Padding
       └─ SingleChildScrollView
          └─ Column
             ├─ Text ("Step 1")
             ├─ SizedBox (height: 8)
             ├─ Text ("오늘 있었던 일을 작성주세요")
             ├─ SizedBox (height: 16)
             ├─ TextField
             │  └─ InputDecoration
             └─ Expanded
                └─ Align
                   └─ ElevatedButton
                      └─ Text ('완료')                

문제정의는 에러 메시지를 보면 할 수 있다.

RenderFlex children have non-zero flex but incoming height constraints are unbounded.
RenderFlex의 자식들에게는 0이 아닌 flex 값이 있지만, 부모로부터 받은 높이 제약 조건이 무한합니다.

  • RenderFlex : Column
  • RenderFlex의 자식 중 flex값을 가진 자식: Expanded
  • 부모 : SingleChildScrollView
  • 부모에게 받은 제약조건 : 자식의 높이에 따라 무한히 늘어나는 높이 조건

Solution: RenderFlex 값을 지정하거나 Child높이를 제한걸거나

1. 정적인 높이 사용하기

  • 이 방법은 그냥 지금처럼 Expanded 처럼 무한히 늘어나는 높이 속성을 가진 위젯을 안쓰는 방법이다.
  • 이 방법으로 문제가 해결되면 아름답겠지만, 우리의 UI 요구사항이 보통 그렇질 못하다.

2. ScrollView + Columne 대신 ListView 사용하기

ListView도 결국 ScrollView 라는 추상클래스를 상속받아서 구현되고 있는 것은 마찬가지이다. 하지만, ListView는 자식 위젯들의 공간에 대해서 자동으로 관리한다. (iOS 에서 UITableView 의 Delegate들 처럼)

덕분에, 사용자는 이미 잘 구현된 높이 계산 객체를 가져다가 사용하기만 하면 된다. 그게 ListView Widget

개선된 구조를 보면 아래와 같다.

WriteDiaryPage
 └─ Scaffold
    ├─ AppBar
    │  └─ BackButton
    └─ Padding
       └─ ListView <---------- 여기
          ├─ Text ("Step 1")
          ├─ SizedBox (height: 8)
          ├─ Text ("오늘 있었던 일을 작성주세요")
          ├─ SizedBox (height: 16)
          ├─ TextField
          │  └─ InputDecoration
          └─ Flexible
             └─ Align
                └─ ElevatedButton
                   └─ Text ('완료')

마무리 및 잡담

  • 지금 문제에 대해서 최대 높이를 설정하는 방식으로 해결할 수도 있다. 하지만 그 방법은 디바이스마다 확인해야할 요소가 상당히 많아질 것이다. 가능하면 ListView로 구성하는게 좋다.
  • 이 문제가 주로 발생하는 것은, 최하단에 BottomButton을 두고 싶고 가운데 TextField나 Spacer 같은것을 사용할 때, 주로 발생한다. Spacer를 사용하여 위젯을 배치하는 방식은 주로 SwiftUI 에서 사용하던 방식이다. 이 방식으로 해도 무리는 없으나, Flutter 는 조금 다르게, 그 위치를 직접 접근하는 파라미터들이 상당히 많다. Stack 하위에 사용하는 Positioned와 같은 위젯이다.
  • 다른선언형을 사용하여 좋은 방식은 차용하되, Flutter의 설계를 존중하여 코딩하는 습관이 중요하다고 느꼈다.
profile
iOS & Flutter

0개의 댓글