Nawet po określeniu wysokości Container GridView mój kod tworzy kwadratowe widżety.
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(),
),
),
);
}
}
Dane wyjściowe powyższego kodu są pokazane po lewej stronie. Jak mogę uzyskać widok GridView z widżetem niestandardowej wysokości, jak pokazano po prawej stronie?
Odpowiedzi:
Kluczem jest
childAspectRatio
. Ta wartość jest używana do określenia układu w programieGridView
. Aby uzyskać żądany aspekt, musisz ustawić go na (itemWidth
/itemHeight
). Rozwiązanie byłoby takie: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(), ), ), ); } }
źródło
GridView.builder
aSliverGridDelegateWithFixedCrossAxisCount
potemchildAspectRatio
jest nagridDelegate
Kilka dni temu przyjechałem tutaj, aby znaleźć sposób na dynamiczną zmianę wysokości, gdy obrazy są ładowane z Internetu i używane
childAspectRatio
nie może tego zrobić, ponieważ ma zastosowanie do wszystkich widżetów w GridView (ta sama wysokość dla każdego).Ta odpowiedź może pomóc komuś, kto chce mieć różną wysokość w zależności od zawartości każdego widżetu:
Znalazłem pakiet o nazwie Flutter Staggered GridView autorstwa Romaina Rastela . Korzystając z tego pakietu możemy zrobić wiele rzeczy, sprawdź przykłady tutaj.
Aby uzyskać to, czego chcemy, możemy użyć
StaggeredGridView.count()
i jego właściwości,staggeredTiles:
a ze względu na jej wartość możesz zmapować cały widget i zastosowaćStaggeredTile.fit(2)
.Przykładowy kod:
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 ), );
Kompletny przykład (kopiowanie, wklejanie i uruchamianie) można znaleźć tutaj .
źródło
crossAxisCount
,crossAxisSpacing
I szerokości do ustaleniawidth
ichildAspectRatio
określaheight
.Zrobiłem trochę obliczeń, aby ustalić relacje między nimi.
var width = (screenWidth - ((_crossAxisCount - 1) * _crossAxisSpacing)) / _crossAxisCount; var height = width / _aspectRatio;
Pełny przykład:
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, ), ), ); }
źródło
To działa na mnie.
Przykładowy kod:
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;
GridView:
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, ); }, )
źródło