Wie kann ich die benutzerdefinierte Höhe für Widget in GridView in Flutter festlegen?


81

Selbst nachdem ich die Höhe für Container GridView angegeben habe, erzeugt mein Code quadratische Widgets.

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> widgetList = ['A', 'B', 'C'];

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Container(
        child: new GridView.count(
          crossAxisCount: 2,
          controller: new ScrollController(keepScrollOffset: false),
          shrinkWrap: true,
          scrollDirection: Axis.vertical,
          children: widgetList.map((String value) {
            return new Container(
              height: 250.0,
              color: Colors.green,
              margin: new EdgeInsets.all(1.0),
              child: new Center(
                child: new Text(
                  value,
                  style: new TextStyle(fontSize: 50.0,color: Colors.white),
                ),
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}

Die Ausgabe des obigen Codes erfolgt wie links gezeigt. Wie kann ich eine GridView mit einem benutzerdefinierten Höhen-Widget erhalten, wie rechts gezeigt?

Ausgabe Erforderliche Ausgabe


Antworten:


147

Der Schlüssel ist der childAspectRatio. Dieser Wert wird verwendet, um das Layout in zu bestimmen GridView. Um den gewünschten Aspekt zu erhalten, müssen Sie ihn auf ( itemWidth/ itemHeight) setzen. Die Lösung wäre folgende:

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<String> widgetList = ['A', 'B', 'C'];

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;

    /*24 is for notification bar on Android*/
    final double itemHeight = (size.height - kToolbarHeight - 24) / 2;
    final double itemWidth = size.width / 2;

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Container(
        child: new GridView.count(
          crossAxisCount: 2,
          childAspectRatio: (itemWidth / itemHeight),
          controller: new ScrollController(keepScrollOffset: false),
          shrinkWrap: true,
          scrollDirection: Axis.vertical,
          children: widgetList.map((String value) {
            return new Container(
              color: Colors.green,
              margin: new EdgeInsets.all(1.0),
              child: new Center(
                child: new Text(
                  value,
                  style: new TextStyle(
                    fontSize: 50.0,
                    color: Colors.white,
                  ),
                ),
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}

Danke für die Antwort.
Hat

Die GridView hat nicht die Eigenschaft childAspectRatio, es sei denn, Sie zählen: - /
Oliver Dixon

1
@OliverDixon, wenn Sie verwenden GridView.builderund SliverGridDelegateWithFixedCrossAxisCountdann childAspectRatioauf demgridDelegate
Fifer Sheep

Wie kann man diese Höhe dynamisch machen?
Dani

12

Vor ein paar Tagen bin ich hierher gekommen, um eine Möglichkeit zu finden, die Höhe dynamisch zu ändern, wenn Bilder aus dem Internet geladen werden, und dies childAspectRatiokann nicht verwendet werden, da dies für alle Widgets in GridView gilt (jeweils dieselbe Höhe).

Diese Antwort kann jemandem helfen, der je nach Widget-Inhalt unterschiedliche Höhen haben möchte:

Ich habe ein Paket namens Flutter Staggered GridView von Romain Rastel gefunden . Mit diesem Paket können wir so viele Dinge tun, um Beispiele hier zu überprüfen.

Um das zu bekommen, was wir wollen, können wir StaggeredGridView.count()und seine Eigenschaft verwenden staggeredTiles:und für seinen Wert können Sie alle Widgets zuordnen und anwenden StaggeredTile.fit(2).

Beispielcode:

StaggeredGridView.count(
    crossAxisCount: 4, // I only need two card horizontally
    padding: const EdgeInsets.all(2.0),
    children: yourList.map<Widget>((item) {
      //Do you need to go somewhere when you tap on this card, wrap using InkWell and add your route
      return new Card(
        child: Column(
          children: <Widget>[
             Image.network(item.yourImage),
             Text(yourList.yourText),//may be the structure of your data is different
          ],
        ),
      );
    }).toList(),

    //Here is the place that we are getting flexible/ dynamic card for various images
    staggeredTiles: yourList.map<StaggeredTile>((_) => StaggeredTile.fit(2))
        .toList(),
    mainAxisSpacing: 3.0,
    crossAxisSpacing: 4.0, // add some space
  ),
);

Ein vollständiges Beispiel (Kopieren, Einfügen und Ausführen) finden Sie hier .


6

crossAxisCount, crossAxisSpacingUnd die Bildschirmbreite bestimmen width, und childAspectRatiobestimmt height.

Ich habe ein bisschen gerechnet, um die Beziehung zwischen ihnen herauszufinden.

var width = (screenWidth - ((_crossAxisCount - 1) * _crossAxisSpacing)) / _crossAxisCount;
var height = width / _aspectRatio;

Vollständiges Beispiel:

double _crossAxisSpacing = 8, _mainAxisSpacing = 12, _aspectRatio = 2;
int _crossAxisCount = 2;

@override
Widget build(BuildContext context) {
  double screenWidth = MediaQuery.of(context).size.width;

  var width = (screenWidth - ((_crossAxisCount - 1) * _crossAxisSpacing)) / _crossAxisCount;
  var height = width / _aspectRatio;

  return Scaffold(
    body: GridView.builder(
      itemCount: 10,
      itemBuilder: (context, index) => Container(color: Colors.blue[((index) % 9) * 100]),
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: _crossAxisCount,
        crossAxisSpacing: _crossAxisSpacing,
        mainAxisSpacing: _mainAxisSpacing,
        childAspectRatio: _aspectRatio,
      ),
    ),
  );
}

1

Geben Sie hier die Bildbeschreibung ein

Es funktioniert für mich.

Beispielcode:

var _crossAxisSpacing = 8;
var _screenWidth = MediaQuery.of(context).size.width;
var _crossAxisCount = 2;
var _width = ( _screenWidth - ((_crossAxisCount - 1) * _crossAxisSpacing)) / _crossAxisCount;
var cellHeight = 60;
var _aspectRatio = _width /cellHeight;

Rasteransicht:

         GridView.builder(
                          padding: EdgeInsets.only(
                              left: 5.0, right: 5.0, top: 10, bottom: 10),
                          shrinkWrap: false,
                          itemCount: searchList.length,
                          gridDelegate:
                              SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: _crossAxisCount,childAspectRatio: _aspectRatio),
                          itemBuilder: (context, index) {
                            final item = searchList[index];
                            return Card(
                              child: ListTile(
                                title: Text(item.name,maxLines: 1,overflow: TextOverflow.ellipsis),
                                trailing: Container(
                                  width: 15,
                                  height: 15,
                                  decoration: BoxDecoration(
                                      color: item.isActive == true
                                          ? Theme.of(context).primaryColor
                                          : Colors.red,
                                      borderRadius: BorderRadius.all(
                                          Radius.circular(50))),
                                ),
                                onTap: () {

                                },
                              ),
                              elevation: 0.5,
                            );
                          },
                        ) 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.