Nicholas Muir
Nicholas Muir

Reputation: 3130

Flutter Gridview or StaggeredGridview variable width /variable number of items to fill column

I am trying to display a gridview that has variable number and width buttons like this:

enter image description here

But what I have ended up with when trying gridview is a fixed number of buttons and fixed widths like this:

enter image description here

Initially I thought this was a problem with the buttons having too much padding by default but that is not the issue, I was able to fix that and still have the same issue with the grid.

I have tried Gridview builder like this:

GridView.builder(
      shrinkWrap: true,
      physics: NeverScrollableScrollPhysics(),
      gridDelegate:
      SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 3.5, mainAxisSpacing: 4, crossAxisSpacing: 4),
      itemBuilder: (BuildContext context, int index) {
        return InkWell(
          onTap: () {
            //Navigator.of(context).pushNamed(HomePageResultsScreen.id);
          },
          child: ButtonTheme(
            minWidth: 16,
            height: 30,
            child: RaisedButton(
              padding: EdgeInsets.all(8.0),
              materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
              color: Colors.white,
              child:
              Center(
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    CachedNetworkImage(fit: BoxFit.contain,
                      height: 40,
                      width: 40,
                      placeholder: (context, url) => new CircularProgressIndicator(),
                      imageUrl: snapshot.data.documents[index]['icon'].toString(),
                    ),
                    Text(snapshot.data.documents[index]['name'].toString(), textAlign: TextAlign.right, style: TextStyle(fontSize:  10, color: Colors.black,),),

                  ],
                ),
              ),
              onPressed: (){

              },
            ),
          ),

        );
      },
      itemCount: snapshot.data.documents.length,
    );

I have also edited the attributes of the builder to haveSliverGridDelagateWithMaxCrossAxisExtent and other attributes. I know the buttons as they are if not placed inside the grid will shrink to minimum size but when in the grid they expand to fill up the whole column.

I have also tried numerous ways by replacing the gridview with a staggered gridview like this:

StaggeredGridView.countBuilder(
        shrinkWrap: true,
        physics: NeverScrollableScrollPhysics(),
        crossAxisCount: 3,
        staggeredTileBuilder: (int index) =>
        new StaggeredTile.count(2, index.isEven ? 2 : 1),
        itemBuilder: (BuildContext context, int index) {
          return InkWell(
            onTap: () {
              //Navigator.of(context).pushNamed(HomePageResultsScreen.id);
            },
            child: ButtonTheme(
              minWidth: 16,
              height: 30,
              child: RaisedButton(
                padding: EdgeInsets.all(8.0),
                materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
                color: Colors.white,
                child:
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    CachedNetworkImage(fit: BoxFit.contain,
                      height: 20,
                      width: 20,
                      placeholder: (context, url) => new CircularProgressIndicator(),
                      imageUrl: snapshot.data.documents[index]['icon'].toString(),
                    ),
                    Text(snapshot.data.documents[index]['name'].toString(), textAlign: TextAlign.center, style: TextStyle(fontSize:  10, color: Colors.black,),),

                  ],
                ),
                onPressed: (){

                },
              ),
            ),

          );
        },
        itemCount: snapshot.data.documents.length,
      ),

I have tried both StaggeredGridView.countBuilder and StaggeredGridView.extent but both of these are even further from what I imagined. It just ends up with a single button per gridview row (looks like a listview).

I am not sure what I am doing wrong or if this is even possible with these widgets.

Thanks for your help

Upvotes: 5

Views: 4757

Answers (3)

Abdullah Khudher
Abdullah Khudher

Reputation: 309

If these containers are not buttons (mean you don't need to click on each of them to do specific something) then you can use Wrap Widget

https://www.youtube.com/watch?v=z5iw2SeFx2M

https://medium.com/flutter-community/flutter-wrap-widget-e1ee0b005b16

Upvotes: 0

BIS Tech
BIS Tech

Reputation: 19514

you have to use StaggeredGridView and you have to find logic to calculate an item width and set StaggeredTile.count.

  final List<String> testing = ['Baby Foods', 'Confectionery', 'Coffee', 'Packets & Units','Packets & Units unis', 'Processed Cheese', 'Factional Care', 'Sauce', 'Sauc'];

    Container(
                width: width,
                child: StaggeredGridView.countBuilder(
                  itemCount: resting.length,
                  physics: NeverScrollableScrollPhysics(),
                  shrinkWrap: true,
                  crossAxisCount: 8,
                  staggeredTileBuilder: (int index) {
                    if (testing[index].length < 5) {
                      return StaggeredTile.count(2, 1);
                    } else if (testing[index].length < 16) {
                      return StaggeredTile.count(3, 1);
                    } else {
                      return StaggeredTile.count(4, 1);
                    }
                  },
                  mainAxisSpacing: 12.0,
                  crossAxisSpacing: 10.0,
                  itemBuilder: (BuildContext context, int index) {
                    return TextButton(
                      child: Text(testing[index]),
                      onPressed: () {},
                    );
                  },
                ),
              ),

Upvotes: 1

anupam das
anupam das

Reputation: 1

# # Staggered View
# ScreenShot
![alt text](https://github.com/Anup2712/flutterAnup/blob/master/StaggeredView/Screenshot.jpg)

# What is it?
A Flutter staggered grid view which supports multiple columns with rows of varying sizes.
It’s a grid layout where the cross axis is divided in multiple equally sized parts, and places elements in optimal position based on available main axis space.
You’ve probably came across some app or website design with staggered grid layout like Pinterest:

# For understand the code

To help you to understand the code, you can see that this grid of 10 tiles is divided into 4 columns:

![alt text](https://github.com/Anup2712/flutterAnup/blob/master/StaggeredView/understanding.png)


# Let's Get Started
<H3>1 - Depend on it</h3>
<h6><b>Add it to your package's pubspec.yaml file</b></h6>
<pre>dependencies:
  fl_chart: ^0.6.1</pre>
<H3>2 - Install it</h3>
<h6><b>Install packages from the command line</b></h6>
<pre>flutter packages get</pre>
<H3>2 - Getting Started</h3>
<h6><b>Import the package:</b></h6>
<pre>import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';</pre>

<pre>import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:ofsdp/pages/home.dart';
import 'package:ofsdp/util/appdrawer.dart';

class AdministrativeUvit extends StatefulWidget {
  @override
  _AdministrativeUvitState createState() => _AdministrativeUvitState();
}

class _AdministrativeUvitState extends State<AdministrativeUvit> {
  var _scaffoldkey = GlobalKey<ScaffoldState>();
  List<StaggeredTile> _staggeredTiles = const <StaggeredTile>[
    const StaggeredTile.count(1, 1),
    const StaggeredTile.count(1, 1),
    const StaggeredTile.count(1, 1),
    const StaggeredTile.count(1, 1),
    const StaggeredTile.count(1, 1.5),
    const StaggeredTile.count(1, 1.5),
  ];

  List<Widget> _tiles = const <Widget>[
  const _Example01Tile(Colors.green, Icons.widgets),
  const _Example01Tile(Colors.lightBlue, Icons.wifi),
  const _Example01Tile(Colors.amber, Icons.panorama_wide_angle),
  const _Example01Tile(Colors.brown, Icons.map),
  const _Example01Tile(Colors.deepOrange, Icons.send),
  const _Example01Tile(Colors.indigo, Icons.airline_seat_flat),
  const _Example01Tile(Colors.red, Icons.bluetooth),
  const _Example01Tile(Colors.pink, Icons.battery_alert),
  const _Example01Tile(Colors.purple, Icons.desktop_windows),
  const _Example01Tile(Colors.blue, Icons.radio),
];
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Image.asset(
          "assets/images/footer.jpg",
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          fit: BoxFit.cover,
        ),
        Scaffold(
            backgroundColor: Colors.transparent,
            appBar: AppBar(
              backgroundColor: Color.fromRGBO(117, 80, 0, 1),
              title: const Text("ADMINISTRATIVE UNIT"),
              actions: <Widget>[
                IconButton(
                  icon: Icon(Icons.home),
                  onPressed: () {
                    Navigator.of(context).pushReplacement(
                      MaterialPageRoute(
                        builder: (context) => HomePage(),
                      ),
                    );
                  },
                )
              ],
            ),
            drawer: AppDrawer(),
            key: _scaffoldkey,

            body: new Padding(
                padding: const EdgeInsets.only(top: 12.0),
                child: new StaggeredGridView.count(
                  crossAxisCount: 2,
                  staggeredTiles: _staggeredTiles,
                  children: _tiles,
                  mainAxisSpacing: 4.0,
                  crossAxisSpacing: 4.0,
                  padding: const EdgeInsets.all(4.0),
                )))
      ],
    );
  }
}
class _Example01Tile extends StatelessWidget {
  const _Example01Tile(this.backgroundColor, this.iconData);

  final Color backgroundColor;
  final IconData iconData;

  @override
  Widget build(BuildContext context) {
    return new Card(
      color: backgroundColor,
      child: new InkWell(
        onTap: () {},
        child: new Center(
          child: new Padding(
            padding: const EdgeInsets.all(4.0),
            child: new Icon(
              iconData,
              color: Colors.white,
            ),
          ),
        ),
      ),
    );
  }
}</pre>

Upvotes: 0

Related Questions