A Widget méret korlátok vagy korlátozások egy elég fontos koncepció a Flutterben. Vagyis annak megértése, hogy a Widgetek méretezése hogyan történik, mitől függ, mi szab határokat egy widget méreteinek, azaz szélességének és hosszúságának.
Alapkoncepció
A legfontosabb, hogy egy widget méretezése egyrészt saját méret szabályaitól is függ, másrészt pedig egy widget méreteit annak szülője (ami rendszerint szintén egy másik widget) is korlátozhatja.
Példa
A megértéshez inkább jöjjön egy példa. Van nekünk a Column widgetünk, ami oszlopszerű megjelenítést tesz lehetővé. A Column widgetnek vannak saját méret szabályai:
- magasság: annyi helyet foglal el függőleges irányban, amennyit csak tud
- szélesség: annyi helyet foglal el, amennyi a Column widget-en belüli legnagyobb tartalom, azaz children widget számára szükséges
A magassághoz jön be még egy fontos tudnivaló, hogy a Column widget magasságát a Column-nak a szülője korlátozza. Ugyanis, ha nem korlátozná, akkor a Column widget szépen kifutna a „világból”, vagyis a képernyőből függőleges irányban. Ennek egyik jó megoldása, ha a Column közvetlenül a Scaffold widget belsejében van, annak body tulajdonságában:
Scaffold(
body: Column(
//...
A Scaffold widget a szélességet és a magasságot egyenlővé teszi a mobil eszköz maximális képernyő szélességével és magasságával.
Minden widget más és másképpen korlátozza a benne levő gyerek widget-ek által elfoglalható területet.
Tehát a közvetlenül a Scaffold widgeten belül a body tulajdonságban megadott Column méretei a következőképpen alakulnak:
- magasság: a mobil maximális képernyő magassága
- szélesség: ez továbbra is a Column widgeten belüli legnagyobb gyerek widgettől függ.
Magyarázat a Flutter DevTools segítségével
A Flutter DevTools megnyitásához a VSCode View menüjéből válasszuk a Command Palette… almenüt, majd kezdjük el gépelni, hogy Flutter: Open DevTools, válasszuk kis ki, majd ezután válasszuk az Open DevTools in Web Browser elemet:
A böngészőben megnyílt a DevTools. A Flutter Inspectorban a Widget Tree mutatja az alkalmazásunkban a teljes Widget fát, ami néha inkább erdő :).
Kiválasztjuk például a Column widgetet a fában:
Jobb oldalon látjuk a Layout Explorer-t. Ez sok mindent megmutat nekünk. Például a Column magasságát:
és a szélességét:
De az értékek alatt közvetlenül ott vannak a méretkorlátok is, amik a szülő Scaffold widgetből származnak. Ha megnézzük a képen a szélességet: 0.0 <= w <= 392.7, akkor azt látjuk, hogy értéke 0 és 392.7 pixel közt lehet, ami a mobil maximális szélessége.
A magasságnál ezt látjuk: 0.0 <= h <= 681.5. Ez gyakorlatilag nem a képernyő méret szó szerinti magassága, hanem a rendelkezésre álló „üres terület”, ami például a fejléc (AppBar) ésatöbbi után következik.
Chart a Column belsejében
Ha tovább nézzük a Layout Explorert, akkor azt látjuk, hogy a Column widget egyik gyereke a Chart widget:
Ennek magasságát „unconstrained”-ként jelüli, ami azt jelenti, hogy a Column a Chart-ra nézve nem kényszerít ki semmilyen magasság korlátot. Illetve nem csak a Chart widget számára, hanem a Column-on belül lévő összes widget számára nincs magasság korlát.
Ez problémát jelenthet a Chart-tal azonos szinten levő Expanded-en belül kicsit mélyebb szinten levő Dismissible widget számára, aminek magassága szintén nem korlátozott:
Ennek okán a Widget fában a Dismissible szülője a ListView magassága sem korlátozott. Így emiatt kifuthat a Column magasságából, amit persze nem fogunk látni, mert levágódik.
Az Expanded feladata
Ezért van fontos szerepe az Expaned widgetnek. Mert ez már beállít a benne levő tartalomnak magasság korlátozásokat. Így a benne levő ListView is csak akkora magasságot foglalhat el, amekkorát az Expanded megenged neki. Az Expanded a magasságot a legnagyobb rendelkezésre álló értékre állítja és ezt a korlátot állítja be a gyerek widgeteknek is.
Row és Expanded
Ugyanez a probléma jelentkezik landscape módban, amit szintén az Expanded oldott meg:
Row(children: [
Expanded(
child: Chart(expenses: _registeredExpenses),
),
Expanded(
child: mainContent,
),
]),
A Chart widgeten belül nincs Row widget. Viszont a Chart widget fájlban van egy Container widget, aminek a szélességét végtelenre állítottuk:
Container(
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.symmetric(
vertical: 16,
horizontal: 8,
),
width: double.infinity,
Ezzel azt állítottuk be, hogy a Container a lehető legnagyobb szélességet foglalja el, ami a rendelkezésre áll. A probléma itt jön képbe, mert a Row widgetnek szintén végtelen a szélessége.
Ennek a „végtelen történetnek” az Expnaded vet véget, ami maximum akkora szélességet ad, amekkora rendelkezésre áll (és nem végtelent / infinity).