skip to Main Content

I’m confuse about the usage of gridview in flutter.
I want to display a list of features with their rates.
The feature component/widget isn’t that big in term of height but when I place them in a gridview the height of each case is way more bigger that it needs to be.

enter image description here

How can I control the height of each case to fit the child height ?

here is my code :

import 'package:flutter/material.dart';
import 'package:project/Components/ReviewComps/AttributeRatings.dart';
    
class ReviewPage extends StatelessWidget {
      const ReviewPage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: SingleChildScrollView(
          child: Container(
            padding: const EdgeInsets.all(20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: const <Widget>[
                AttributeRatings(),
              ],
            ),
          ),
        ));
      }
    }

here is my gridview that create problems :

import 'package:flutter/material.dart';

class AttributeRatings extends StatelessWidget {
  const AttributeRatings({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var featureList = [
      _featureItems(4),
      _featureItems(3.2),
      _featureItems(1),
    ];
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        const Text("Features average rating"),
        GridView.count(
          crossAxisCount: 2,
          crossAxisSpacing: 20,
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          children: featureList,
        ),
      ],
    );
  }
}

Container _featureItems(double rate) {
  return Container(
    color: Colors.red,
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            const Text('Feature'),
            Text(rate.toString()),
          ],
        ),
        Stack(
          children: [
            Container(
              height: 2,
              width: double.infinity,
              color: const Color(0xffDBDFED),
            ),
            FractionallySizedBox(
              widthFactor: rate / 5,
              child: Container(
                height: 2,
                color: const Color(0xff39B0EA),
              ),
            )
          ],
        )
      ],
    ),
  );
}

2

Answers


  1. Chosen as BEST ANSWER

    The solution I found is quite complicated but I changed the gridview to a list view and put rows inside. The most dificult was to work with odd lengths lists here is my solution :

    import 'package:flutter/material.dart';
    
    class AttributeRatings extends StatelessWidget {
      const AttributeRatings({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        var featureList = [4, 3.2, 4, 2, 3.2];
        double nbRows = featureList.length % 2 == 0
            ? (featureList.length / 2)
            : (featureList.length / 2) + 1;
        var reworkedFeatureList = [];
        if (featureList.length % 2 == 0) {
          for (var i = 0; i < (featureList.length - 1) / 2; i++) {
            reworkedFeatureList.add([featureList[i * 2], featureList[(i * 2) + 1]]);
          }
        } else {
          final retVal = featureList.removeLast();
          for (var i = 0; i < (featureList.length - 1) / 2; i++) {
            reworkedFeatureList.add([featureList[i * 2], featureList[(i * 2) + 1]]);
          }
          reworkedFeatureList.add([retVal, -1]);
        }
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            const Text("Features average rating"),
            ListView.separated(
              separatorBuilder: (context, index) {
                return const SizedBox(height: 12);
              },
              itemCount: nbRows.toInt(),
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemBuilder: (context, index) =>
                  _featureItemsRow(reworkedFeatureList[index]),
            ),
          ],
        );
      }
    }
    
    Row _featureItemsRow(var rates) {
      return Row(
        children: [
          Expanded(
              child: Padding(
            padding: const EdgeInsets.only(right: 10.0),
            child: _featureItem(rates[0].toDouble()),
          )),
          Expanded(
              child: Padding(
            padding: const EdgeInsets.only(left: 10.0),
            child: _featureItem(rates[1].toDouble()),
          )),
        ],
      );
    }
    
    Column _featureItem(double rate) {
      if (rate == -1) {
        return Column();
      } else {
        return Column(
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                const Text('Feature'),
                Text(rate.toString()),
              ],
            ),
            Stack(
              children: [
                Container(
                  height: 2,
                  width: double.infinity,
                  color: const Color(0xffDBDFED),
                ),
                FractionallySizedBox(
                  widthFactor: rate / 5,
                  child: Container(
                    height: 2,
                    color: const Color(0xff39B0EA),
                  ),
                )
              ],
            )
          ],
        );
      }
    }
    

  2. You can give childAspectRatio to customise a height as following

    import 'package:flutter/material.dart';
    
    class AttributeRatings extends StatelessWidget {
      const AttributeRatings({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        var featureList = [
          _featureItems(4),
          _featureItems(3.2),
          _featureItems(1),
        ];
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            const Text("Features average rating"),
            GridView.count(
              crossAxisCount: 2,
              crossAxisSpacing: 20,
              childAspectRatio: 4,//You may have to calculate based on screen size
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              children: featureList,
            ),
          ],
        );
      }
    }
    
    Container _featureItems(double rate) {
      return Container(
        color: Colors.red,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                const Text('Feature'),
                Text(rate.toString()),
              ],
            ),
            Stack(
              children: [
                Container(
                  height: 2,
                  width: double.infinity,
                  color: const Color(0xffDBDFED),
                ),
                FractionallySizedBox(
                  widthFactor: rate / 5,
                  child: Container(
                    height: 2,
                    color: const Color(0xff39B0EA),
                  ),
                )
              ],
            )
          ],
        ),
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search