Shahrear Bin Amin
Shahrear Bin Amin

Reputation: 1115

Horizontal viewport was given unbounded height while using PageView.Builder

I'm working on simple quiz app with BLoC pattern. Tried to implement swipe feature for each quiz with PageView.Builder, here is my code

class _QuizScreenState extends State<QuizScreen> {
  @override
  void initState() {
    context.read<QuizInfoBloc>().add(GetQuizStat("1"));

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      backgroundColor: kSecondaryColor,
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        elevation: 0,
        actions: [],
      ),
      body: Container(
        decoration: BoxDecoration(color: kSecondaryColor),
        width: double.infinity,
        height: double.infinity,
        child: SafeArea(
            child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 0),
          child: Column(
            children: [
              Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
                child: ProgressBar(),
              ),
              Spacer(
                flex: 1,
              ),
              Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
                child: BlocConsumer<QuizInfoBloc, QuizInfoState>(
                  listener: (context, state) {
                    // TODO: implement listener
                  },
                  builder: (context, state) {
                    if (state is QuizInfoLoaded) {
                      return PageView.builder(
                          itemCount: state.quiz.questions.length,
                          itemBuilder: (context, index) => QuestionCard(
                              question: state.quiz.questions[index]));
                    } else {
                      return Container(
                        height: 0,
                        width: 0,
                      );
                    }
                  },
                ),
              ),
              Spacer(
                flex: 4,
              ),
              BottomButtons(),
              SizedBox(
                height: 20,
              ),
              // AnswerExplanation(
              //   correctOrWrong: kGreenColor,
              // ),
            ],
          ),
        )),
      ),
    );
  }
}

I've tried with wrapping PageView.Builder with Expanded which was wrapped with Column. But still getting a different error

              Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
                child: BlocConsumer<QuizInfoBloc, QuizInfoState>(
                  listener: (context, state) {
                    // TODO: implement listener
                  },
                  builder: (context, state) {
                    if (state is QuizInfoLoaded) {
                      return Column(
                        children: [
                          Expanded(
                            child: PageView.builder(
                                itemCount: state.quiz.questions.length,
                                itemBuilder: (context, index) => QuestionCard(
                                    question: state.quiz.questions[index])),
                          ),
                        ],
                      );
                    } else {
                      return Container(
                        height: 0,
                        width: 0,
                      );
                    }
                  },
                ),
              ),

RenderFlex children have non-zero flex but incoming height constraints are unbounded.

QuestionCard

class _QuestionCardState extends State<QuestionCard> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(kDefaultPadding / 2),
      child: Column(
        children: [
          Text(
            this.widget.question.questionText,
            style: Theme.of(context)
                .textTheme
                .headline5
                ?.copyWith(color: Colors.white, fontWeight: FontWeight.bold),
          ),
          SizedBox(
            height: 30,
          ),
          ListView.builder(
              scrollDirection: Axis.vertical,
              shrinkWrap: true,
              itemCount: this.widget.question.options.length,
              itemBuilder: (BuildContext context, int index) {
                return OptionUI(option: this.widget.question.options[index]);
              })
        ],
      ),
    );
  }
}


Upvotes: 0

Views: 255

Answers (1)

enzo
enzo

Reputation: 11496

  1. Since you already have a kSecondaryColor as backgroundColor of your Scaffold, you don't need a Container as body of your Scaffold:
Scaffold(
  extendBodyBehindAppBar: true,
  backgroundColor: kSecondaryColor,
  appBar: AppBar(
    backgroundColor: Colors.transparent,
    elevation: 0,
    actions: [],
  ),
  body: SafeArea(
    // child: ...
  ),
)
  1. A SafeArea widget is meant to be used on the top-level widget tree:
SafeArea(
  Scaffold(
    extendBodyBehindAppBar: true,
    backgroundColor: kSecondaryColor,
    appBar: AppBar(
      backgroundColor: Colors.transparent,
      elevation: 0,
      actions: [],
    ),
    body: Padding(
      // child: ...
    ),
  )
)
  1. Wrap an Expanded into the Padding of your BlocConsumer:
Column(
  children: [
    Padding(
      padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
      child: ProgressBar(),
    ),
    Spacer(flex: 1),
    Expanded(
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding / 2),
        child: BlocConsumer<QuizInfoBloc, QuizInfoState>(
          listener: (context, state) {
            // TODO: implement listener
          },
          builder: (context, state) {
            if (state is QuizInfoLoaded) {
              return PageView.builder(
                  itemCount: state.quiz.questions.length,
                  itemBuilder: (context, index) =>
                      QuestionCard(question: state.quiz.questions[index]));
            } else {
              return Container(height: 0, width: 0);
            }
          },
        ),
      ),
    ),
    Spacer(flex: 4),
    BottomButtons(),
    SizedBox(height: 20),
    // AnswerExplanation(correctOrWrong: kGreenColor),
  ],
);

You didn't provide the ProgressBar, QuestionCard and BottomButtons widgets, so if the error persists you should check them, but I think these changes should suffice.

Upvotes: 2

Related Questions