Flutter

[Flutter] ListView constraintsError

Hayden_ 2023. 4. 6. 03:30

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late SharedPreferences prefs;
  final List<String> testList = ["확언하기", "감사하기", "명상하기"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SingleChildScrollView(
          physics: const AlwaysScrollableScrollPhysics(),
          child: Column(
            children: [
              const SizedBox(
                height: 80,
              ),
              (testList.isNotEmpty)
                  ? Flexible(
                      child: ListView.builder(
                        shrinkWrap: true,
                        itemBuilder: (BuildContext ctx, int idx) {
                          return Text(testList[idx]);
                        },
                        itemCount: testList.length,
                      ),
                    )
                  : const Text("add habits"),
            ],
          ),
        ),
      ),
    );
  }
}

한참 고생한 에러이다. ListView.builder를 사용해서 리스트를 만들려고 했는데 testList에 지금은 3개만 넣었지만 나중에는 더 많아 질 수 있기 때문에 SingleChildScrollView로 감싸고 ListView를 사용했는데 계속 constraintsError가 발생하였다.

 

constraintsError은 주로 아래의 이유로 발생한다고 한다. 

1. 부모 위젯의 크기가 충분하지 않아 자식 위젯이 충분한 공간을 차지하지 못할 때
2. 자식 위젯의 크기가 부모 위젯의 제약 조건을 벗어날 때
3. 위젯이 제한된 공간 내에서 작동하도록 강제하는 제약 조건을 설정하지 않았을 때

 

그래서 보통 ListView를 사용했을 때 constraintsError가 나면 ListView에 Expanded나 Flexible 위젯으로 감싸고 shrinkWrap 속성을 true로 해주면 문제가 대부분 해결 되는 것 같은데 나는 도저히 해결이 안된는 것이다.

 

그래서 찾은 해결법은 SingleChildScrollView을 지워주는 것이었다.

ListView도 스크롤 기능이 있는데 SingleChildScrollView의 스크롤 기능과 충돌하여 문제가 생긴 것이다.

 

그래서 SingleChildScrollView을 지워줘서 해결을 했는데

 

SingleChildScrollView와 ListView를 동시에 사용하고 싶은 경우가 생길 수도 있기 때문에 동시에 사용할 수 있는 방법을 찾아보자.

 

1. ListView에 SizedBox로 height를 지정해주는 방법

2. ListView의 속성에 physics: NeverScrollableScrollPhysics()  을 추가해준다. 이 속성의 의미는 ListView의 스크롤을 사용하지 않는다는 의미다. 그래서 SingleChildScrollView와의 스크롤 중복을 방지하는 것이다.