13 β Layout II: Stack va Constraints¶
β¬ οΈ Oldingi: 12 β Layout I: Row, Column, Flex Β· π README Β· Keyingi: 14 β Material 3, Cupertino va theming β‘οΈ
Bu bobda: o'tgan bobda
RowvaColumnbilan widgetlarni yonma-yon va ustma-ust terib o'rgandingiz. Endi navbat β bir widgetni boshqasining ustiga qo'yish (Stack/Positioned) va Flutter'da layout aslida qanday hisoblanishini tushunishga keldi. Bu β beginnerlar eng ko'p qoqiladigan, lekin tushunilgach hammasi "klik" bo'ladigan bob. SizStack,Positioned,Positioned.fillbilan qatlamli interfeys (rasm ustida matn, avatar ustida nishon) quryapsiz;Align/Center/Paddingbilan joylashtirishni boshqarasiz; Flutter'ning mashhur layout qoidasini β "cheklov pastga, o'lcham yuqoriga, joyni ota belgilaydi" β qadam-baqadam o'zlashtirasiz;BoxConstraints/ConstrainedBox,LayoutBuilder,MediaQuery,SafeAreavaWrap'ni ko'rasiz; oxirida rasm-banner, teg-bulut va torayganda ustunga aylanadigan responsive ikki-panel quramiz.
Nima uchun bu bob alohida?¶
O'tgan bobda Row/Column bilan widgetlarni ketma-ket terdingiz. Lekin haqiqiy ilovalarda ko'pincha narsalar bir-birining ustida turadi: rasm ustida sarlavha, profil suratining burchagidagi yashil "onlayn" nuqtasi, fotosurat ostidagi qoraygan gradient. Bularning hammasi Row/Column bilan emas, Stack bilan quriladi.
Va yana bir narsa bor β har bir beginner shu joyda hayron qoladi: "Men Containerga width: 100 berdim, lekin u baribir butun ekranni egalladi. Nega?" Bu savolga javob β Flutter layout algoritmi. Uni bir marta tushunsangiz, layout bilan bog'liq xatolaringizning aksariyati o'z-o'zidan tushunarli bo'lib qoladi. Shuning uchun bu bobni diqqat bilan o'qing β bu sarmoya keyingi barcha boblarda foyda beradi.
Stack β qatlamlarni ustma-ust qo'yish¶
Stack (so'zma-so'z "uyum", "to'plam") β bolalarini bir-birining ustiga qo'yadigan layout widget. Xuddi stolga bir necha varaq qog'ozni ustma-ust tashlagandek: pastdagisi ko'rinmay qoladi, ustidagisi ko'rinadi.
Stack(
children: [
Container(color: Colors.blue, width: 200, height: 200), // pastki qatlam
const Icon(Icons.star, size: 48), // ustidagi qatlam
],
)
Muhim qoida: children ro'yxatidagi tartib β chizish tartibi. Ro'yxatdagi birinchi element eng pastda, oxirgisi eng ustda chiziladi. Ya'ni keyingi bolalar oldingilarning ustiga tushadi.
Default holatda barcha bolalar Stackning yuqori-chap burchagiga joylashadi (bir-birining ustiga). Buni ikki yo'l bilan boshqaramiz: alignment (hammasini bir tomonga) yoki Positioned (har birini aniq joyga).
Positioned β bolani aniq joyga mixlash¶
Stack ichidagi bolani aniq koordinataga qo'yish uchun uni Positioned bilan o'raymiz. Positioned to'rt chetdan masofa beradi: top, right, bottom, left.
Stack(
children: [
Image.network('https://.../rasm.jpg'), // asos
Positioned(
top: 12,
right: 12,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(12),
),
child: const Text('YANGI', style: TextStyle(color: Colors.white)),
),
),
],
)
Bu yerda top: 12, right: 12 degani: "bolani yuqoridan 12 piksel, o'ngdan 12 piksel masofada joylashtir". Mana shunday qilib avatar ustidagi nishon (badge) yoki rasm burchagidagi yorliq quriladi.
π‘
topvabottomning ikkalasini ham bersangiz, bolaning balandligi shu ikki chet orasiga cho'ziladi. Xuddi shundayleft+rightenini belgilaydi. Faqat bittasini bersangiz β bola o'z tabiiy o'lchamida qoladi, shunchaki o'sha chetga "yopishadi".
Positioned.fill β butun maydonni egallash¶
Agar bola Stackning butun maydonini to'ldirishini istasangiz, Positioned.fill ishlating β bu Positioned(top: 0, right: 0, bottom: 0, left: 0) ning qisqa shakli:
Bu rasm ustiga gradient parda yoyish uchun juda qo'l keladi (matn o'qilishi uchun fotosuratning pastini qoraytirish).
Amaliyot: rasm ustida sarlavha (banner)¶
Endi o'rganganlarimizni birlashtirib, klassik banner quramiz β fotosurat, uning pastida qoraygan gradient va ustida oq matn:
Stack(
children: [
// 1-qatlam: asos rasm
Image.network(
'https://picsum.photos/600/300',
width: double.infinity,
height: 200,
fit: BoxFit.cover,
),
// 2-qatlam: pastdan yuqoriga qoraygan gradient (matn o'qilishi uchun)
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.center,
colors: [Colors.black.withValues(alpha: 0.7), Colors.transparent],
),
),
),
),
// 3-qatlam: pastki-chapda sarlavha matni
const Positioned(
left: 16,
bottom: 16,
child: Text(
'Toshkent kechasi',
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
),
// 4-qatlam: o'ng-yuqorida "YANGI" nishoni
Positioned(
top: 12,
right: 12,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(12),
),
child: const Text('YANGI', style: TextStyle(color: Colors.white)),
),
),
],
)
E'tibor bering β qatlamlar tartibi mantiqiy: avval rasm, ustiga gradient (rasmni qoraytiradi), eng ustiga matn va nishon (ular doim ko'rinib turadi). Tartibni almashtirsangiz (masalan gradientni matndan keyin qo'ysangiz), matn gradient ostida qolib ketadi.
β οΈ
Stackning o'lchami.Stacko'ziningPositionedsiz (oddiy) bolalarining eng kattasiga moslab kattalashadi. Yuqoridagi misoldaImageaniq balandlik (height: 200) berganligi uchunStackham shuncha bo'ladi. Agar barcha bolalarPositionedbo'lsa,Stackka o'lcham beradigan hech narsa qolmaydi β uniSizedBoxyoki balandligi aniq ota ichiga qo'ying.
Align, Center va Alignment koordinatalari¶
Centerni 10-bobdan bilasiz β bolani ota maydonining markaziga qo'yadi. Align esa undan kuchliroq: bolani istalgan tomonga qo'yadi.
Align(
alignment: Alignment.bottomRight, // pastki-o'ng burchak
child: FloatingActionButton(onPressed: () {}, child: const Icon(Icons.add)),
)
Alignmentning tayyor qiymatlari intuitiv: Alignment.topLeft, Alignment.topCenter, Alignment.center, Alignment.bottomRight va hokazo.
Lekin ulardan tashqari Alignment aslida koordinata tizimi. U Alignment(x, y) ko'rinishida ikkita son oladi, ikkalasi ham -1 dan +1 gacha:
x = -1β eng chap,x = 0β markaz,x = +1β eng o'ng;y = -1β eng tepa,y = 0β markaz,y = +1β eng past.
Demak Alignment.center aslida Alignment(0, 0), Alignment.bottomRight esa Alignment(1, 1). Oraliq qiymatlar ham mumkin: Alignment(0.5, -0.5) β markazdan biroz o'ngda va tepada.
π‘
Stackning hamalignment:parametri bor β uPositionedsiz bolalarni qayerga yig'ishni belgilaydi (defaultAlignment.topLeft). MasalanStack(alignment: Alignment.center, children: [...])β oddiy bolalarni markazga to'playdi.
FractionallySizedBox β ota o'lchamining ulushi¶
Ba'zan bolaning o'lchamini piksel emas, foiz bilan berish kerak: "ota enining 70 foizi". Buni FractionallySizedBox qiladi:
FractionallySizedBox(
widthFactor: 0.7, // ota enining 70%
child: Container(height: 40, color: Colors.indigo),
)
Bu progress-bar yoki ekran kengligiga moslashadigan tugmalar uchun qulay.
Flutter layout algoritmi β eng muhim tushuncha¶
Mana, bobning yuragi. Agar boshqa hamma narsani unutsangiz ham, shu jumlani eslab qoling:
Cheklov pastga tushadi. O'lcham yuqoriga ko'tariladi. Joyni ota belgilaydi. (Constraints go down. Sizes go up. Parent sets position.)
Bu nima degani? Flutter ekranni chizishdan oldin har bir widgetning o'lchamini va o'rnini hisoblashi kerak. U buni widget daraxti bo'ylab uch bosqichda qiladi.
Bosqichma-bosqich¶
1. Cheklov pastga tushadi. Har bir ota widget o'z bolasiga cheklov (constraint) beradi. Cheklov β bu to'rtta son: minWidth, maxWidth, minHeight, maxHeight. Ma'nosi: "Sen shu eni va bo'yi oralig'ida bo'lishing shart". Masalan ekranning ildizi: "sen 0..360 eni, 0..640 bo'yi oralig'ida bo'l".
2. O'lcham yuqoriga ko'tariladi. Bola shu cheklov ichida o'ziga mos o'lchamni tanlaydi va uni otasiga qaytaradi. Masalan Text "menga 180Γ24 yetarli" deydi (cheklov ruxsat bersa). Ota bu o'lchamni o'z bolasidan eshitadi.
3. Joyni ota belgilaydi. Endi ota bolaning o'lchamini biladi va uni o'z ichida qayerga qo'yishni hal qiladi. Center markazga qo'yadi, Align(bottomRight) pastki-o'ngga qo'yadi. Bola o'zining o'rnini bilmaydi β buni doim ota belgilaydi.
Aniq misol bilan "yurib chiqamiz"¶
Quyidagi oddiy daraxtni olaylik:
Endi algoritmni qadam-baqadam kuzatamiz:
- Ekran
Centerga cheklov beradi:maxWidth: 360, maxHeight: 640(telefon ekrani). Centershu cheklovni o'zgartirmasdan (lekin bo'sh qilib β pastda tushuntiramiz)Paddingga uzatadi.Paddinghar tomondan 16px ajratadi, demak bolasiga toraytirilgan cheklov beradi:maxWidth: 360 β 32 = 328.Text('Salom')o'z matnini o'lchaydi: masalan52Γ20. Bu cheklovga sig'adi, shuning uchunText"men 52Γ20" deb yuqoriga qaytaradi.Paddingbolasining o'lchamiga 32 qo'shadi β84Γ52deb otasiga qaytaradi.Centerbu o'lchamni oladi vaPaddingni ekranning aniq markaziga joylashtiradi.
Mana shu β Flutter har bir kadr (frame) uchun butun daraxt bo'ylab bajaradigan jarayon.
Nega "tight" va "loose" muhim?¶
Cheklovlar ikki xil bo'ladi:
- Tight (qattiq):
min == max. Ya'ni "aniq shu o'lchamda bo'l, boshqa variant yo'q". Masalan ekranning ildizi bolasiga "aniq butun ekran bo'l" deydi. - Loose (bo'sh):
min = 0,maxesa biror chegara. Ya'ni "0 dan max gacha istagan o'lchamingni tanla".
Mana endi eng ko'p beriladigan savolga javob: nega Container(width: 100) ba'zan e'tiborga olinmaydi?
// 1-holat: Container e'tiborga OLINMAYDI
Container(width: 100, color: Colors.blue)
// agar bu widget body to'g'ridan-to'g'ri bo'lsa, butun ekranni egallaydi!
// 2-holat: Container ENINI hurmat qiladi
Center(
child: Container(width: 100, color: Colors.blue),
)
1-holatda Scaffold.body Containerga tight cheklov beradi ("aniq butun ekran bo'l"). Container esa tight cheklovga bo'ysunishga majbur β shuning uchun width: 100 e'tiborga olinmaydi.
2-holatda esa Center bolasiga loose cheklov beradi ("0..360 oralig'ida istaganingni tanla"). Endi Container o'zining width: 100 ini erkin tanlay oladi. Center aynan shu uchun ko'p ishlatiladi β u cheklovni "bo'shatadi".
π‘ Qoida: bola otasi bergan cheklovni hech qachon buza olmaydi.
Container(width: 100)aslida "men iloji bo'lsa 100 bo'lishni xohlayman" degani. Agar cheklov tight bo'lsa β bu istak inobatga olinmaydi. Layout xatosida birinchi savol: "bu widgetga otasi qanday cheklov berdi?"
BoxConstraints va ConstrainedBox¶
Ba'zan cheklovni o'zingiz qo'shimcha cheklamoqchi bo'lasiz β masalan "bu kartaning eni 400 pikseldan oshmasin" (keng ekranlarda matn juda cho'zilib ketmasligi uchun). Buni ConstrainedBox qiladi:
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Card(child: Text('Bu karta eng ko\'pi 400px keng bo\'ladi')),
)
BoxConstraints β bu o'sha to'rtta sonni (minWidth, maxWidth, minHeight, maxHeight) o'rab turuvchi obyekt. Foydali konstruktorlari:
BoxConstraints(maxWidth: 400)β eni 400 dan oshmasin;BoxConstraints.expand()β bor joyni to'liq egalla;BoxConstraints.tightFor(width: 100, height: 50)β aniq shu o'lcham.
π‘
Containerningconstraints:parametri ham bor β ya'niConstrainedBoxni alohida o'rashning o'rnigaContainer(constraints: BoxConstraints(maxWidth: 400), child: ...)deb yozsa bo'ladi.
LayoutBuilder β ota cheklovini o'qish¶
Hozirgacha cheklov "yashirin" edi β uni Flutter ichida boshqarardi. Lekin ba'zan biz otamiz qancha joy berganini bilib, shunga qarab boshqacha UI qurmoqchimiz. Masalan: "ekran keng bo'lsa β ikki panel yonma-yon, tor bo'lsa β ustma-ust".
Mana shu yerda LayoutBuilder keladi. U builder funksiyasiga ota bergan constraintsni uzatadi, siz esa shunga qarab qaror qabul qilasiz:
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 600) {
// keng ekran β yonma-yon
return Row(
children: const [
Expanded(child: RoyxatPanel()),
Expanded(child: TafsilotPanel()),
],
);
} else {
// tor ekran β ustma-ust
return Column(
children: const [
RoyxatPanel(),
TafsilotPanel(),
],
);
}
},
)
E'tibor bering β MediaQuery (pastda) butun ekran o'lchamini beradi, LayoutBuilder esa aynan shu widgetga ajratilgan joyni beradi. Shuning uchun LayoutBuilder aniqroq: u widget ekranning yarmida tursa ham, faqat o'sha yarmini "ko'radi". Bu responsive (moslashuvchan) interfeysning asosi β biz buni 28-bobda (platforma va moslashuv) chuqurlashtiramiz.
MediaQuery va SafeArea β ekran haqida ma'lumot¶
MediaQuery butun qurilma ekrani haqidagi ma'lumotlarni beradi: o'lcham, orientatsiya, tizim panellari (notch, status bar):
final size = MediaQuery.of(context).size; // ekran o'lchami
print(size.width); // masalan 392.0
print(size.height);
final orientation = MediaQuery.of(context).orientation; // portrait / landscape
MediaQuery.of(context).size β ekranning umumiy eni va bo'yi. Buni "ekranning yarmini egallasin" kabi qarorlarda ishlatasiz.
SafeArea β bu juda muhim, amaliy widget. Zamonaviy telefonlarda yuqorida notch (kamera o'yig'i), status bar, pastda esa navigatsiya chizig'i bor. Agar UI'ngiz ulardan ostiga tushib qolsa, matn o'qilmay qoladi. SafeArea bolasini shu "xavfli" zonalardan avtomatik chetlatadi:
Scaffold(
body: SafeArea(
child: Column(
children: [ /* kontent endi notch ostiga tushmaydi */ ],
),
),
)
π‘
ScaffoldAppBarbilan ishlatilganda yuqorisini odatda o'zi himoya qiladi, lekinAppBarsiz to'liq ekranli UI qurganingizdaSafeAreani unutmang.
Wrap β joy tugaganda yangi qatorga o'tish¶
Row bilan bog'liq mashhur muammoni eslang: agar bolalar enga sig'masa, "overflow" (sariq-qora chiziqli ogohlantirish) chiqadi. Wrap aynan shu muammoni hal qiladi β u Row kabi, lekin joy tugaganda bolalarni avtomatik yangi qatorga o'tkazadi:
Wrap(
spacing: 8, // bolalar orasidagi gorizontal oraliq
runSpacing: 8, // qatorlar orasidagi vertikal oraliq
children: const [
Chip(label: Text('Flutter')),
Chip(label: Text('Dart')),
Chip(label: Text('Mobile')),
Chip(label: Text('iOS')),
Chip(label: Text('Android')),
Chip(label: Text('Web')),
],
)
Bu teg-bulut (tag cloud), filtr-chiplar, ranglar palitrasi kabi "qancha sig'sa shuncha, qolgani pastga" interfeyslar uchun ideal. alignment: parametri bilan qatorlar ichidagi tekislashni ham boshqarasiz.
AspectRatio va IntrinsicHeight (qisqacha)¶
AspectRatio β bolaning nisbatini (eni:bo'yi) saqlaydi. Masalan video yoki rasmni doim 16:9 ko'rsatish:
U otadan kelgan enga moslab bo'yini avtomatik hisoblaydi (yoki aksincha) β shunda nisbat buzilmaydi.
IntrinsicHeight β Row ichidagi bolalarni eng balandiga tenglashtiradi (masalan ikki kartani bir balandlikda qilish). Foydali, lekin bitta ogohlantirish bilan:
β οΈ Unumdorlik (performance) ogohlantirishi.
IntrinsicHeight(vaIntrinsicWidth) Flutter'ni bolalarni ikki marta o'lchashga majbur qiladi β bu sekinroq. Faqat haqiqatan kerak bo'lganda, kichik daraxtlarda ishlating. Ko'p hollarda muammoniExpandedyoki aniq balandlik bilan hal qilsa bo'ladi.
Layoutni nazorat qilish (debugging)¶
Layout xatolari boshlanuvchini cho'chitadi, lekin Flutter yordam beradi:
BoxConstraints forces an infinite width/height/ "unbounded constraints" xatosi. Bu eng tez-tez uchraydigan xato. Ma'nosi: bolaga "cheksiz joy" berildi-yu, bola o'sha cheksizlikni to'ldirishga urinyapti. Klassik sabab βColumnichigaListViewqo'yish (Columnbolasiga cheksiz balandlik beradi,ListViewesa "qancha bersang shuncha olaman" deydi β cheksizlik). Yechim:ListViewniExpandedbilan o'rash yoki aniq balandlik berish.- Flutter Inspector / "Debug Paint". DevTools'dagi Inspector widget daraxtini ko'rsatadi va biror widgetni tanlasangiz, unga qanday cheklov berilganini aytadi. Debug Paint rejimini yoqsangiz, har bir widgetning chegaralari, paddinglari ekranda chiziq bilan ko'rinadi β "bu bo'sh joy qayerdan keldi?" degan savolga darhol javob beradi. Buni 29-bobda (testing va debugging) batafsil ko'ramiz.
π‘ Layout xatosini ko'rganda vahima qilmang. Xato matnini diqqat bilan o'qing β Flutter odatda qaysi widget muammo qilayotganini va nima qilish kerakligini aniq aytadi. Eng birinchi savol doim bitta: "bu widgetga otasi qanday cheklov berdi β tight, loose yoki cheksiz?"
Birgalikda: responsive profil sahifasi¶
Endi bobning hammasini birlashtiramiz. Quramiz: tepada rasm-banner (Stack), pastida teg-bulut (Wrap), va keng ekranda ikki ustunga, tor ekranda bitta ustunga aylanadigan tartib (LayoutBuilder).
import 'package:flutter/material.dart';
void main() => runApp(const ProfilApp());
class ProfilApp extends StatelessWidget {
const ProfilApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
),
home: Scaffold(
appBar: AppBar(title: const Text('Profil')),
body: SafeArea(
child: LayoutBuilder(
builder: (context, constraints) {
final banner = _buildBanner();
final teglar = _buildTeglar();
// keng ekran β banner va teglar yonma-yon
if (constraints.maxWidth >= 600) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: banner),
Expanded(
child: Padding(
padding: const EdgeInsets.all(16),
child: teglar,
),
),
],
);
}
// tor ekran β ustma-ust
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
banner,
Padding(padding: const EdgeInsets.all(16), child: teglar),
],
);
},
),
),
),
);
}
Widget _buildBanner() {
return Stack(
children: [
Image.network(
'https://picsum.photos/600/300',
width: double.infinity,
height: 200,
fit: BoxFit.cover,
),
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.center,
colors: [Colors.black.withValues(alpha: 0.7), Colors.transparent],
),
),
),
),
const Positioned(
left: 16,
bottom: 16,
child: Text(
'Oqil Imomnazarov',
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
),
Positioned(
top: 12,
right: 12,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(12),
),
child: const Text('Onlayn', style: TextStyle(color: Colors.white)),
),
),
],
);
}
Widget _buildTeglar() {
const teglar = ['Flutter', 'Dart', 'Mobile', 'iOS', 'Android', 'Web', 'UI'];
return Wrap(
spacing: 8,
runSpacing: 8,
children: [
for (final t in teglar) Chip(label: Text(t)),
],
);
}
}
Bu ilovani ishga tushiring, keyin oynani (web/desktop'da) yoki emulyatorni kengaytiring-toraytiring β 600 piksel chegarasidan o'tganda layout avtomatik ustunβqator orasida almashganini ko'rasiz. Mana shu β bitta kod bazasidan turli ekranlarga moslashadigan interfeys.
Keyingi qadam¶
Tabriklaymiz β siz layout'ning eng chuqur tushunchasini o'zlashtirdingiz. Endi bilasiz: widgetlarni Stack bilan qatlamlash, Align/Center bilan joylashtirish, va eng muhimi β Flutter cheklovlarni pastga, o'lchamlarni yuqoriga tashiydi, joyni esa ota belgilaydi. Bu qoidani bilgan dasturchi uchun layout xatolari endi sir emas.
Keyingi 14-bobda ko'rinishga β uslub va mavzuga (theming) o'tamiz: Material 3 rang tizimi, ThemeData, dark mode, tipografiya va iOS uslubidagi Cupertino widgetlari. Ilovangiz nafaqat to'g'ri joylashgan, balki chiroyli ham bo'ladi.
Mashqlar¶
Oson¶
Stackningchildrenro'yxatida tartib nimani belgilaydi? Birinchi va oxirgi element qatlamlarning qaysi biriga (pastki/ustki) tushadi?Positioned(top: 12, right: 12, child: ...)nima qiladi?Positioned.fillesa nima qiladi va u qanday qisqartma?Alignmentkoordinata tizimidaxvayqanday qiymatlar oladi?Alignment.centervaAlignment.bottomRightsonli ko'rinishda nimaga teng?- Flutter layout qoidasini bitta jumlada yozing (uchta qism: cheklov, o'lcham, joy).
WrapRowdan nimasi bilan farq qiladi? Qaysi holatdaWrapishlatish kerak?
O'rta¶
- Nima uchun
Container(width: 100, color: Colors.blue)to'g'ridan-to'g'riScaffold.bodyga qo'yilsa butun ekranni egallaydi, lekinCenterichiga qo'yilsa 100 piksel bo'ladi? "Tight" va "loose" cheklov tushunchalari bilan tushuntiring. LayoutBuildervaMediaQueryorasidagi farqni ayting: ularning har biri qaysi o'lchamni beradi va qaysi biri "shu widgetga ajratilgan joyni" beradi?SafeAreanima muammoni hal qiladi? Qaysi holatda uni ishlatish ayniqsa muhim?IntrinsicHeightnima qiladi va nega undan ehtiyot bo'lib foydalanish kerak?
Qiyin¶
- To'liq, kompilyatsiya bo'ladigan
Stackyozing: pastida ko'kContainer(eni va bo'yi 150), uning o'ng-yuqori burchagida (top: 8, right: 8) qizil dumaloq "nuqta" (eni va bo'yi 16) bo'lsin. Bu β bildirishnoma nishonining (notification badge) asosiy g'oyasi. - Bir o'quvchi
ColumnichigaListViewqo'ydi va "unbounded height" xatosini oldi. Bu xato nega chiqdi (cheklovlar tilida tushuntiring) va uni qanday tuzatish mumkin? LayoutBuilderishlatib, agar ajratilgan kenglik 400 dan kichik bo'lsa bittaText('Tor'), aks holdaText('Keng')ko'rsatadigan widget yozing.
Yechimlar
1. children ro'yxatidagi tartib β chizish tartibi. Birinchi element eng pastki qatlamga (asos), oxirgi element eng ustki qatlamga tushadi. Keyingi bolalar oldingilarning ustiga chiziladi.
2. Positioned(top: 12, right: 12, child: ...) β bolani Stackning yuqori chetidan 12 piksel, o'ng chetidan 12 piksel masofaga joylaydi. Positioned.fill esa bolani Stackning butun maydoniga yoyadi β bu Positioned(top: 0, right: 0, bottom: 0, left: 0) ning qisqa shakli.
3. x va y ikkalasi ham -1 dan +1 gacha qiymat oladi: x = -1 chap, 0 markaz, +1 o'ng; y = -1 tepa, 0 markaz, +1 past. Demak Alignment.center = Alignment(0, 0), Alignment.bottomRight = Alignment(1, 1).
4. Cheklov (constraints) pastga tushadi (ota β bola), o'lcham (size) yuqoriga ko'tariladi (bola β ota), joyni (position) ota belgilaydi.
5. Row bolalarni faqat bitta gorizontal qatorga teradi va joy yetmasa "overflow" xatosi beradi. Wrap esa joy tugaganda bolalarni avtomatik yangi qatorga o'tkazadi. Wrapni soni o'zgaruvchan, enga sig'masligi mumkin bo'lgan elementlarda (teg-chiplar, filtrlar) ishlatamiz.
6. Scaffold.body o'z bolasiga tight cheklov beradi β "aniq butun ekran bo'l, boshqa variant yo'q". Bola tight cheklovga bo'ysunishga majbur, shuning uchun Containerning width: 100 istagi inobatga olinmaydi. Center esa bolasiga loose cheklov beradi β "0 dan max gacha istaganingni tanla". Endi Container o'zining 100 pikselini erkin tanlay oladi. Ya'ni Center cheklovni "bo'shatib" beradi.
7. MediaQuery.of(context).size butun qurilma ekrani o'lchamini beradi. LayoutBuilder esa builderdagi constraints orqali aynan shu widgetga ajratilgan joyni beradi. Demak "shu widgetga ajratilgan joy" β LayoutBuilder. Shuning uchun widget ekranning bir qismida tursa, LayoutBuilder aniqroq qaror berishga yordam beradi.
8. SafeArea UI'ni qurilmaning tizim zonalari (notch/kamera o'yig'i, status bar, pastki navigatsiya chizig'i) ostiga tushib qolishidan saqlaydi. U bolani shu zonalardan avtomatik chetlatadi. Ayniqsa AppBarsiz, to'liq ekranli interfeys qurganda muhim β aks holda kontent notch yoki status bar ostida qolib o'qilmay qoladi.
9. IntrinsicHeight Row ichidagi bolalarni eng balandiga tenglashtiradi. Undan ehtiyot bo'lish kerak, chunki u Flutter'ni bolalarni ikki marta o'lchashga majbur qiladi β bu unumdorlikni (performance) pasaytiradi. Faqat haqiqatan kerak bo'lganda, kichik daraxtlarda ishlatish tavsiya etiladi.
10.
Stack(
children: [
Container(width: 150, height: 150, color: Colors.blue),
Positioned(
top: 8,
right: 8,
child: Container(
width: 16,
height: 16,
decoration: const BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
),
),
],
)
11. Column o'z bolalariga vertikal yo'nalishda cheksiz (unbounded) balandlik beradi β "qancha kerak bo'lsa shuncha bo'l". ListView esa "menga bergan butun balandlikni olaman" deydi. Ikkalasi uchrashganda: ListView cheksizlikni to'ldirishga urinadi β "unbounded height" xatosi. Tuzatish: ListViewni Expanded bilan o'rash (Expanded(child: ListView(...))) β shunda Column qolgan aniq balandlikni beradi; yoki ListViewga SizedBox(height: ...) orqali aniq balandlik berish; yoki shrinkWrap: true ishlatish (kichik ro'yxatlar uchun).
12.
β¬ οΈ Oldingi: 12 β Layout I: Row, Column, Flex Β· π README Β· Keyingi: 14 β Material 3, Cupertino va theming β‘οΈ