15 β Asosiy UI widgetlar¶
β¬ οΈ Oldingi: 14 β Material 3, Cupertino va theming Β· π README Β· Keyingi: 16 β StatefulWidget va setState β‘οΈ
Bu bobda: endi qurilish g'ishtlari bilan tanishamiz β deyarli har bir ilova ishlatadigan asosiy UI widgetlar katalogi. Material 3 tugmalar ierarxiyasini (
FilledButton,ElevatedButton,FilledButton.tonal,OutlinedButton,TextButton,IconButton,FloatingActionButton) va qaysi birini qachon ishlatishni o'rganamiz;TextFieldva uningInputDecorationqismlarini bo'lak-bo'lak ko'ramiz; tanlov boshqaruvlari βCheckbox,Switch,Radio,Slider; tarkibni guruhlovchiCard; ro'yxatlarning ishchi otiListTile;Chipoilasi; va foydalanuvchiga fikr-mulohaza (feedback) berish βSnackBar,AlertDialog, progress indikatorlari. Oxirida bularni birlashtirib sozlamalar ekrani va login formasi layout'ini quramiz. Muhim ogohlantirish: bu yerda widgetlarning shaklini ko'rsatamiz; ularni jonli (bosilganda haqiqatan o'zgaradigan) qilish uchun holat kerak β bu keyingi, 16-bob mavzusi.
Katalog boshlanishidan oldin: nega bu boblar muhim¶
Oldingi boblarda layout'ni (Row, Column, Container, Stack) va Material 3 mavzusini (14-bob) ko'rdik β ya'ni narsalarni qayerga qo'yishni va ular qanday rang olishini bilamiz. Endi esa shu joylarga nima qo'yishni o'rganamiz: tugmalar, matn maydonlari, kalitlar (switch), kartochkalar.
Buni oshxonadagi idishlar to'plamiga o'xshating. Sizda allaqachon javon (layout) va dizayn (theme) bor. Bu bob β idishlarning o'zi: piyola, tarelka, qoshiq. Har birini bir marta tanisangiz, keyin har bir ovqatda (ilovada) qayta-qayta ishlatasiz. Shuning uchun bu bobni lug'at sifatida o'qing β hozir bir o'qib chiqing, keyin kerak bo'lganda qaytib kelib qaraysiz.
π‘ Bitta tushunchani oldindan aytib qo'yamiz. Quyidagi ko'p widgetlarda
onPressed:,onChanged:,onTap:kabi parametrlar bor β bular foydalanuvchi tegiganda chaqiriladigan funksiya. Bu yerda biz ularning ichida ko'pinchaprint(...)yozamiz yoki "16-bobda jonli qilamiz" deymiz. Sababi: tugma bosilganda ekrandagi qiymatni haqiqatan o'zgartirish uchunStatefulWidgetvasetStatekerak β bu 16-bobning mavzusi. Hozircha shaklni o'rganamiz.
Tugmalar β Material 3 ierarxiyasi¶
Tugma β foydalanuvchi bosadigan, biror harakatni boshlaydigan element. Flutter'da bitta "tugma" emas, balki bir nechta turdagi tugma bor. Nega? Chunki ekrandagi har bir tugma bir xil darajada muhim emas. "Saqlash" tugmasi "Bekor qilish"dan muhimroq; "Batafsil" havolasi ulardan ham past. Material 3 shu muhimlik darajasini β urg'u (emphasis) β tugma ko'rinishi orqali ifodalashni taklif qiladi.
Qoida sodda: ekrandagi eng muhim, asosiy harakatni eng baland urg'uli tugma bilan ko'rsating, qolganlarini pastroq bilan. Bitta ekranda odatda faqat bitta yuqori urg'uli (to'la rangli) tugma bo'lishi kerak β aks holda foydalanuvchining ko'zi qayerga qarashni bilmaydi.
FilledButton β yuqori urg'u (asosiy harakat)¶
Eng muhim, birlamchi harakat uchun. To'la rangli foni bilan ko'zga eng yaqqol tashlanadi.
Eng muhim parametr β onPressed:. Bu tugma bosilganda ishga tushadigan funksiya. Va mana bitta juda muhim qoida:
π‘
onPressed: nullβ tugmani o'chiradi (disabled). AgaronPressedganullbersangiz, tugma kulrang va bosilmaydigan bo'lib qoladi. Bu juda foydali: masalan, forma to'liq to'ldirilmaguncha "Yuborish" tugmasininullqilib o'chirib qo'yasiz. (Buni dinamik qilish β qachonnull, qachon funksiya β ham holatga bog'liq, 16-bob.)
const FilledButton(
onPressed: null, // o'chirilgan β kulrang, bosilmaydi
child: Text('Hozircha mumkin emas'),
)
ElevatedButton va FilledButton.tonal β o'rta urg'u¶
ElevatedButton β biroz soyali (ko'tarilgan) tugma. Rangli yoki rasmli fon ustida joylashganda yaxshi ajraladi.
FilledButton.tonal β FilledButton'ning yumshoqroq, ochroq rangli ko'rinishi. Ikkilamchi, lekin baribir e'tiborni tortadigan harakatlar uchun ("yuqori"dan past, "outlined"dan baland).
OutlinedButton β o'rta/past urg'u¶
Faqat hoshiya (chiziq) bilan, ichi bo'sh. Ko'pincha "Bekor qilish" yoki ikkilamchi tanlov uchun, FilledButton yonida juftlik bo'lib turadi.
TextButton β past urg'u¶
Eng kam ko'zga tashlanadigan tugma β faqat matn, fonsiz va hoshiyasiz. "Batafsil", "Parolni unutdingizmi?", dialog ichidagi tugmalar uchun.
Ikonkali tugmalar (.icon konstruktori)¶
Yuqoridagi har bir tugmaning .icon ko'rinishi bor β matn yoniga ikonka qo'shadi. Bu harakatning ma'nosini tezroq tushuntiradi.
FilledButton.icon(
onPressed: () => print('yuklab olinmoqda'),
icon: const Icon(Icons.download),
label: const Text('Yuklab olish'), // bu yerda child emas, label!
)
π‘ E'tibor bering: oddiy konstruktorda
child:bor edi,.iconkonstruktorida esaicon:valabel:bo'ladi.
IconButton β faqat ikonka¶
Matnsiz, faqat ikonka. Joy tejaydi β shuning uchun AppBarda, satr ichida, ro'yxat oxirida ko'p ishlatiladi (qidiruv, sozlamalar, yopish belgisi).
IconButton(
onPressed: () => print('qidiruv'),
icon: const Icon(Icons.search),
tooltip: 'Qidirish', // ustiga bosib turganda chiqadigan maslahat
)
FloatingActionButton (FAB) β ekranning asosiy harakati¶
Dumaloq, suzib turadigan tugma β odatda ekranning pastki-o'ng burchagida. Ekrandagi eng asosiy harakat uchun ishlatiladi (masalan "yangi xabar", "+"). U Scaffoldning maxsus uyasiga joylanadi:
Scaffold(
appBar: AppBar(title: const Text('Vazifalar')),
body: const Center(child: Text('Ro\'yxat shu yerda')),
floatingActionButton: FloatingActionButton(
onPressed: () => print('yangi vazifa'),
tooltip: 'Qo\'shish',
child: const Icon(Icons.add),
),
)
Tugma ko'rinishini sozlash β styleFrom¶
Tugma rangi yoki o'lchamini o'zgartirmoqchi bo'lsangiz, har bir tugma turining styleFrom yordamchisi bor. U ButtonStyle obyektini qulay tarzda yasab beradi:
FilledButton(
onPressed: () {},
style: FilledButton.styleFrom(
backgroundColor: Colors.green,
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
),
child: const Text('Yashil tugma'),
)
π‘ Ko'pincha buning kerak ham bo'lmaydi: 14-bobdagi
ColorSchemeallaqachon barcha tugmalarga uyg'un ranglar beradi.styleFromni faqat alohida tugmani ajratmoqchi bo'lganingizda ishlating.
TextField β matn kiritish maydoni¶
TextField β foydalanuvchi klaviaturadan matn yozadigan maydon: ism, email, parol, izoh. Bu deyarli har bir formada bor.
Eng muhim parametr β decoration:, unga InputDecoration(...) beriladi. Aynan shu maydonning ko'rinishini β yorliq, maslahat matni, ikonkalar, hoshiya β boshqaradi. Quyidagi rasmda har bir qism qaysi xususiyatdan kelishini ko'ring:
TextField(
decoration: InputDecoration(
labelText: 'Email', // suzuvchi yorliq
hintText: 'misol@pochta.uz', // bo'sh holatdagi maslahat
helperText: 'Emailingizni kiriting', // pastdagi yordam matni
prefixIcon: const Icon(Icons.email), // oldidagi ikonka
border: const OutlineInputBorder(), // to'liq hoshiya
),
)
InputDecorationning eng ko'p ishlatiladigan qismlari:
| Xususiyat | Nima qiladi |
|---|---|
labelText |
Maydon ustida turuvchi yorliq (fokuslanganda suzib yuqoriga chiqadi). |
hintText |
Maydon bo'sh bo'lganda ichida ko'rinadigan kulrang maslahat. |
helperText |
Maydon ostidagi kichik yordam matni. |
prefixIcon / suffixIcon |
Maydon boshidagi / oxiridagi ikonka. |
border: OutlineInputBorder() |
Maydonni to'liq ramka (hoshiya) bilan o'raydi. |
Klaviatura turi va parol¶
keyboardType β qaysi turdagi klaviatura chiqishini belgilaydi (raqamlar uchun raqamli klaviatura qulayroq). obscureText: true esa yozilgan matnni nuqtalar bilan yashiradi β parol uchun shart.
// Raqam kiritish uchun
TextField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(labelText: 'Yosh'),
)
// Email uchun
TextField(
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(labelText: 'Email'),
)
// Parol uchun β yozilgan belgilar yashiriladi
TextField(
obscureText: true,
decoration: const InputDecoration(
labelText: 'Parol',
prefixIcon: Icon(Icons.lock),
),
)
Kiritilgan matnni qanday o'qiymiz?¶
Foydalanuvchi yozgan matnni olishning ikki yo'li bor:
onChanged:β har bir belgi o'zgarganda chaqiriladigan funksiya, yangi matnni argument sifatida beradi:
controller:βTextEditingControllerorqali maydonni boshqarish (matnni o'qish, tozalash, oldindan to'ldirish).
π‘
TextEditingController, forma validatsiyasi (Form+TextFormFieldbilan "email noto'g'ri" kabi tekshiruvlar) β bularning hammasini 17-bobda keyin, formalarga bag'ishlangan bo'limda batafsil ko'ramiz. HozirchaonChangedbilan matnni "eshitishni" biling β bu yetarli.
Tanlov boshqaruvlari β Checkbox, Switch, Radio, Slider¶
Bular foydalanuvchi tanlov qiladigan widgetlar: belgilash katakchasi, yoqish/o'chirish kaliti, variantlardan birini tanlash, qiymatni surg'ich bilan o'rnatish.
Hammasining umumiy shakli bir xil: ular value (hozirgi qiymat) va onChanged (qiymat o'zgarganda chaqiriladigan funksiya) oladi.
β οΈ Juda muhim: bu widgetlar o'zicha o'zgarmaydi. Siz
value:ga bergan qiymatni ko'rsatadi, xolos. Foydalanuvchi bosgandaonChangedchaqiriladi β lekin ekranda haqiqatan belgi qo'yilishi uchun sizvalueni yangilab, qaytadan qurishingiz kerak. Buning uchun esa holat (state) lozim. Quyida widgetlarning shaklini ko'rsatamiz; ularni jonli qilishni 16-bobda o'rganamiz. Shuning uchunonChangedichida hozircha
Checkbox β belgilash katakchasi¶
Ha/yo'q tanlovi uchun (masalan "Shartlarga roziman").
Checkbox(
value: true, // hozirgi holat (belgilangan)
onChanged: (yangi) {
print('Checkbox: $yangi'); // 16-bobda value'ni yangilaymiz
},
)
Switch β yoqish/o'chirish kaliti¶
Sozlamalarda biror narsani yoqish/o'chirish uchun (Wi-Fi, bildirishnomalar).
Radio / RadioGroup β bir nechtadan bittasini tanlash¶
Radio β bir-birini istisno qiladigan variantlar uchun (faqat bittasi tanlangan bo'ladi: masalan "Erkak / Ayol"). Material 3'da bir guruh radiolarni RadioGroup bilan o'rab, umumiy tanlangan qiymatni boshqariladi:
RadioGroup<String>(
groupValue: 'erkak', // hozir tanlangan variant
onChanged: (yangi) => print('Tanlandi: $yangi'),
child: const Column(
children: [
RadioListTile<String>(
value: 'erkak',
title: Text('Erkak'),
),
RadioListTile<String>(
value: 'ayol',
title: Text('Ayol'),
),
],
),
)
Slider β surg'ich bilan qiymat tanlash¶
Diapazondagi qiymatni (ovoz balandligi, yorqinlik) tanlash uchun.
Slider(
value: 0.4, // 0.0 dan 1.0 gacha (standart diapazon)
onChanged: (yangi) => print('Slider: $yangi'),
)
Qulay ko'rinishlar β CheckboxListTile va SwitchListTile¶
Amalda siz ko'pincha katakcha yoniga yorliq matni ham qo'yishni istaysiz. Buni qo'lda Row qurmasdan, tayyor CheckboxListTile va SwitchListTile widgetlari hal qiladi β ular Checkbox/Switchni ListTile (matnli satr) ichiga joylab beradi:
SwitchListTile(
value: true,
onChanged: (yangi) => print('Bildirishnoma: $yangi'),
title: const Text('Bildirishnomalar'),
subtitle: const Text('Yangiliklar haqida xabar berish'),
secondary: const Icon(Icons.notifications),
)
Sozlamalar ekranida aynan shu ko'rinish eng ko'p kerak bo'ladi.
Card β tarkibni guruhlash¶
Card β burchaklari yumaloqlangan, biroz soyali "kartochka". U bog'liq ma'lumotlarni bir guruh qilib, qolganidan vizual ajratadi (mahsulot, profil, xabar kartochkasi).
Card(
elevation: 2, // soya darajasi (balandlik)
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text('Flutter kursi', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
SizedBox(height: 8),
Text('0 dan ekspertgacha. 26 ta bob.'),
],
),
),
)
π‘
Cardning o'zi ichki bo'shliq (padding) bermaydi β shuning uchun ichiga ko'pinchaPaddingqo'yiladi.shape:orqali burchak shaklini,elevation:orqali soyani sozlashingiz mumkin.
ListTile β ro'yxatlarning ishchi oti¶
ListTile β eng ko'p ishlatiladigan satr widget. Ro'yxatlarda, menyularda va ayniqsa sozlamalar ekranlarida har bir qatorni shu yasaydi. U tayyor, standart joylashuvga ega bo'lgan to'rt uyani beradi:
ListTile(
leading: const Icon(Icons.person), // chapdagi ikonka/avatar
title: const Text('Profil'), // asosiy matn
subtitle: const Text('Ism, rasm, bio'), // qo'shimcha matn
trailing: const Icon(Icons.chevron_right), // o'ngdagi belgi (o'q)
onTap: () => print('Profil ochildi'), // butun satr bosiladi
)
ListTilening uyalari:
| Uya | Odatda nima qo'yiladi |
|---|---|
leading |
Chapdagi ikonka yoki avatar. |
title |
Asosiy matn (sarlavha). |
subtitle |
Title ostidagi qo'shimcha matn. |
trailing |
O'ngdagi element β o'q (Icons.chevron_right), Switch yoki Chip. |
onTap |
Butun satr bosilganda chaqiriladi. |
π‘
onTapβListTileni butunlay bosiladigan qiladi: foydalanuvchi satrning istalgan joyiga tegsa ishlaydi, faqat ikonkaga emas. Sozlamalar va menyularda navigatsiya uchun shu juda qulay.
Chip oilasi β ixcham yorliq/tanlovlar¶
Chip β kichik, dumaloq burchakli "tabletka" shaklidagi element. Teglar, filtrlar yoki kichik harakatlar uchun ishlatiladi.
// Oddiy yorliq
const Chip(label: Text('Flutter'))
// Bosiladigan harakat chip'i
ActionChip(
label: const Text('Ulashish'),
avatar: const Icon(Icons.share, size: 18),
onPressed: () => print('ulashildi'),
)
// Filtr chip'i β tanlanadigan/o'chiriladigan (holat kerak β 16-bob)
FilterChip(
label: const Text('Bepul'),
selected: true,
onSelected: (tanlandi) => print('Filtr: $tanlandi'),
)
ActionChip bosilganda biror harakat qiladi; FilterChip esa tanlanadigan (belgilanadigan) bo'lib, filtrlar uchun ishlatiladi β uning ham haqiqiy tanlanishi holatga bog'liq.
Fikr-mulohaza (feedback) widgetlari¶
Foydalanuvchiga "men sizni eshitdim" deb bildirish ham UI'ning muhim qismi. Eng ko'p ishlatiladiganlari:
SnackBar β pastdan chiqadigan qisqa xabar¶
Ekran pastida bir necha soniya ko'rinib yo'qoladigan kichik xabar ("Saqlandi", "Internet yo'q"). Uni ScaffoldMessenger orqali ko'rsatasiz:
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Saqlandi!')),
);
},
child: const Text('Saqlash'),
)
π‘
ScaffoldMessenger.of(context)βcontextdan eng yaqinScaffoldning "xabarchisi"ni topadi va unga SnackBar ko'rsatishni buyuradi.contexthaqida 10-bobda gaplashgandik β bu widgetning daraxtdagi o'rni.
AlertDialog β modal dialog¶
Foydalanuvchidan tasdiq so'raydigan oyna ("O'chirishni xohlaysizmi?"). showDialog bilan chiqariladi:
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('O\'chirish'),
content: const Text('Rostdan ham o\'chirilsinmi?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context), // dialogni yopish
child: const Text('Yo\'q'),
),
FilledButton(
onPressed: () => Navigator.pop(context),
child: const Text('Ha'),
),
],
),
);
E'tibor bering β dialog ichidagi tugmalar ham aynan o'sha tanish TextButton va FilledButton (past urg'u "Yo'q", yuqori urg'u "Ha"). Dialoglar va navigatsiyani to'liq 19-bobda ko'ramiz.
Progress indikatorlari β kutilmoqda¶
Biror narsa yuklanayotganini bildiradi:
const CircularProgressIndicator() // aylanadigan dumaloq
const LinearProgressIndicator() // gorizontal chiziq
Qiymat bermasangiz, ular cheksiz (qancha vaqt qolganini bilmaganda) animatsiya qiladi. Aniq foiz ma'lum bo'lsa, value: 0.7 kabi bersa, to'lib boradigan ko'rsatkich bo'ladi.
Hammasini birlashtiramiz¶
Endi bu widgetlarni alohida emas, birga β haqiqiy ekranlarga yig'amiz. Ana shunda ularning kuchini his qilasiz.
1) Sozlamalar ekrani β ListTile + SwitchListTile¶
Sozlamalar ekrani β bu deyarli butunlay ListTile va SwitchListTilelardan tuzilgan ro'yxat. Card ichiga joylab, chiroyli guruh qilamiz:
import 'package:flutter/material.dart';
class SozlamalarEkrani extends StatelessWidget {
const SozlamalarEkrani({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Sozlamalar')),
body: ListView(
children: [
const Card(
margin: EdgeInsets.all(12),
child: Column(
children: [
SwitchListTile(
value: true,
onChanged: _stub, // 16-bobda jonli qilamiz
secondary: Icon(Icons.notifications),
title: Text('Bildirishnomalar'),
),
SwitchListTile(
value: false,
onChanged: _stub,
secondary: Icon(Icons.dark_mode),
title: Text('Tungi rejim'),
),
],
),
),
Card(
margin: const EdgeInsets.all(12),
child: Column(
children: [
ListTile(
leading: const Icon(Icons.person),
title: const Text('Profil'),
subtitle: const Text('Ism, rasm'),
trailing: const Icon(Icons.chevron_right),
onTap: () => print('Profil'),
),
ListTile(
leading: const Icon(Icons.lock),
title: const Text('Maxfiylik'),
trailing: const Icon(Icons.chevron_right),
onTap: () => print('Maxfiylik'),
),
],
),
),
],
),
);
}
// Switch hozircha qiymatni o'zgartira olmaydi (holat 16-bobda) β
// shuning uchun shunchaki "tegildi" deb chop etamiz.
static void _stub(bool yangi) => print('Switch: $yangi');
}
π‘
ListViewβ bolalarni vertikal aylantiriladigan (scroll) ro'yxat qilib joylaydi (ko'p elementlardaColumndan farqli ravishda chetiga sig'maganda aylantirib ko'rsatadi). Ro'yxatlarni keyingi bobda batafsil ko'ramiz.
2) Login formasi layout'i β TextField + FilledButton¶
Login ekrani β ikkita TextField (email va parol) va bitta yuqori urg'uli FilledButton. Pastida past urg'uli TextButton ("Parolni unutdingizmi?"):
import 'package:flutter/material.dart';
class LoginEkrani extends StatelessWidget {
const LoginEkrani({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Kirish')),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const TextField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email',
prefixIcon: Icon(Icons.email),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
const TextField(
obscureText: true,
decoration: InputDecoration(
labelText: 'Parol',
prefixIcon: Icon(Icons.lock),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 24),
// To'la kenglikdagi asosiy tugma
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: () => print('Kirish bosildi'),
child: const Text('Kirish'),
),
),
TextButton(
onPressed: () => print('Parolni tiklash'),
child: const Text('Parolni unutdingizmi?'),
),
],
),
),
);
}
}
π‘
SizedBox(width: double.infinity, child: FilledButton(...))β bu tugmani ota maydonning to'liq kengligiga cho'zadi. Login tugmalari odatda shunday keng bo'ladi. Hozircha yozilgan matnni o'qimaymiz (controller β 17-bob), faqat layout va tugmani ko'rsatyapmiz.
3) Kartochkalar ro'yxati¶
Card + ListTile birikmasi β eng ko'p uchraydigan "kontent ro'yxati" namunasi (mahsulotlar, maqolalar, kontaktlar):
ListView(
children: const [
Card(
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: ListTile(
leading: Icon(Icons.book),
title: Text('Flutter kitobi'),
subtitle: Text('26 bob Β· boshlovchilar uchun'),
trailing: Icon(Icons.chevron_right),
),
),
Card(
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: ListTile(
leading: Icon(Icons.code),
title: Text('Dart asoslari'),
subtitle: Text('9 bob Β· til poydevori'),
trailing: Icon(Icons.chevron_right),
),
),
],
)
Keyingi qadam¶
Endi sizda ilovaning asosiy qurilish g'ishtlari bor: tugmalar, matn maydonlari, kalitlar, kartochkalar, ro'yxat satrlari va fikr-mulohaza widgetlari. Ekranni "tashqi" tarzda qurishni β qanday ko'rinishini β to'liq bilasiz.
Lekin bir narsa hali yetishmaydi: bu ekranlar jonli emas. Switchni bossangiz o'zgarmaydi, TextFieldga yozsangiz tugma yonmaydi, Sliderni sursangiz qiymat qotib turadi. Buning sababi β biz hech qayerda holatni (state) yangilamadik.
Aynan shu β keyingi 16-bobning mavzusi: StatelessWidgetdan StatefulWidgetga o'tib, setState orqali holatni o'zgartirishni va shu bilan UI'ni qaytadan qurishni o'rganamiz. Ana shunda bu bobdagi barcha widgetlar haqiqatan tirik bo'ladi.
Mashqlar¶
Oson¶
- Material 3 tugmalarini urg'u (emphasis) bo'yicha eng balanddan eng pastgacha tartiblang:
TextButton,FilledButton,OutlinedButton. Har biri uchun bittadan haqiqiy misol harakat yozing (masalan "Saqlash"). onPressed: nulltugmaga nima qiladi? Bu qaysi vaziyatda foydali bo'ladi?InputDecorationning quyidagi xususiyatlari nima qilishini bir jumlada yozing:labelText,hintText,prefixIcon,border.ListTilening to'rt uyasini (leading,title,subtitle,trailing) ayting va har biriga odatda nima qo'yilishini yozing.- Parol uchun
TextFieldda qaysi parametrnitrueqilish kerak, va u nima qiladi?
O'rta¶
- To'liq, kompilyatsiya bo'ladigan
Scaffoldyozing:AppBarda "Mahsulot" sarlavhasi,bodyda markazda bittaCard, kartochka ichidaListTile(leadingβIcons.shopping_cart,titleβ "Telefon",subtitleβ "1 200 000 so'm"). - Login formasidagi "Kirish" tugmasi nega
SizedBox(width: double.infinity, ...)ichiga o'ralgan? Buni olib tashlasak nima o'zgaradi? Checkbox,Switch,Sliderwidgetlarining umumiy ikkita parametri qaysi? Nega bu kitobning hozirgi bosqichida ularningonChangedichigaprintyozyapmiz, qiymatni o'zgartirmayapmiz?
Qiyin¶
- Bitta sozlamalar
Cardi yozing: ichida ikkitaSwitchListTile("Bildirishnomalar", "Tungi rejim") va bittaListTile("Til",trailingβ o'q-belgi,onTapbilan).onChanged/onTapichidaprintishlating va kod nega hozir jonli emasligini bir izoh bilan tushuntiring. FilledButton,FilledButton.tonal,OutlinedButton,TextButtonβ bularning hammasi bitta "Buyurtma berish" ekranida bo'lsa, qaysi harakatga qaysi birini berasiz? Misol harakatlarni o'zingiz tanlab, tanlovingizni urg'u ierarxiyasi bilan asoslang.
Yechimlar
1. Eng balanddan eng pastgacha: FilledButton (yuqori urg'u β asosiy harakat, masalan "Saqlash") β OutlinedButton (o'rta urg'u β ikkilamchi, masalan "Bekor qilish") β TextButton (past urg'u β masalan "Batafsil"). To'la rangli fon eng ko'p e'tibor tortadi, faqat hoshiya o'rtacha, faqat matn eng kam.
2. onPressed: null tugmani o'chiradi (disabled) β u kulrang bo'lib qoladi va bosilmaydi. Bu, masalan, forma to'liq to'ldirilmaguncha "Yuborish" tugmasini faolsiz qilib turish uchun foydali β foydalanuvchi xato vaziyatda tugmani bosa olmaydi.
3.
- labelText β maydon ustida turuvchi yorliq (fokuslanganda yuqoriga suzib chiqadi).
- hintText β maydon bo'sh bo'lganda ichida ko'rinadigan kulrang maslahat matni.
- prefixIcon β maydon boshidagi (chap tomondagi) ikonka.
- border β maydonni o'rab turuvchi hoshiya (OutlineInputBorder() to'liq ramka beradi).
4.
- leading β chapdagi ikonka yoki avatar.
- title β asosiy matn (sarlavha).
- subtitle β title ostidagi qo'shimcha matn.
- trailing β o'ngdagi element: o'q-belgi (Icons.chevron_right), Switch yoki Chip.
5. obscureText: true. U yozilgan har bir belgini nuqta bilan yashiradi, shunda parol ekranda ochiq ko'rinmaydi.
6.
import 'package:flutter/material.dart';
class MahsulotEkrani extends StatelessWidget {
const MahsulotEkrani({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Mahsulot')),
body: const Center(
child: Card(
child: ListTile(
leading: Icon(Icons.shopping_cart),
title: Text('Telefon'),
subtitle: Text('1 200 000 so\'m'),
),
),
),
);
}
}
7. SizedBox(width: double.infinity, ...) tugmani ota maydonning to'liq kengligiga cho'zadi β login tugmalari odatda shunday keng bo'ladi (bosish oson va vizual jihatdan asosiy harakat ekani bilinadi). Uni olib tashlasak, FilledButton faqat o'z matni sig'adigancha (matn kengligida) qisqaradi va o'rtada kichik tugma bo'lib qoladi.
8. Umumiy ikkita parametr β value (hozirgi qiymat) va onChanged (qiymat o'zgarganda chaqiriladigan funksiya). print yozyapmiz, chunki bu widgetlar o'zicha o'zgarmaydi: ekranda haqiqatan belgi qo'yilishi uchun valueni yangilab, widgetni qaytadan qurish kerak β buning uchun esa holat (StatefulWidget + setState) lozim, u esa 16-bobda. Hozircha faqat shaklni ko'rsatyapmiz.
9.
Card(
margin: const EdgeInsets.all(12),
child: Column(
children: [
SwitchListTile(
value: true,
onChanged: (yangi) => print('Bildirishnoma: $yangi'),
secondary: const Icon(Icons.notifications),
title: const Text('Bildirishnomalar'),
),
SwitchListTile(
value: false,
onChanged: (yangi) => print('Tungi rejim: $yangi'),
secondary: const Icon(Icons.dark_mode),
title: const Text('Tungi rejim'),
),
ListTile(
leading: const Icon(Icons.language),
title: const Text('Til'),
trailing: const Icon(Icons.chevron_right),
onTap: () => print('Til tanlash'),
),
],
),
)
SwitchListTilening valuesi qat'iy (true/false) yozib qo'yilgan. Foydalanuvchi switch'ni bossa onChanged ishlaydi (print chiqadi), lekin value o'zgarmagani uchun switch ekranda ko'tarilgan holatda qoladi. Uni jonli qilish uchun valueni o'zgaruvchidan olib, setState bilan yangilash kerak β 16-bob.
10. Tipik tanlov (urg'u ierarxiyasiga ko'ra):
- FilledButton β "Buyurtma berish" β ekranning asosiy harakati, eng baland urg'u (faqat bitta bo'lishi kerak).
- FilledButton.tonal yoki OutlinedButton β "Savatga qo'shish" β muhim, lekin birlamchi emas (o'rta urg'u).
- OutlinedButton β "Bekor qilish" β ikkilamchi, faqat hoshiya bilan.
- TextButton β "Mahsulot tafsilotlari" yoki "Yetkazib berish shartlari" β past urg'uli, havola kabi.
Asos: bitta ekranda foydalanuvchini bitta asosiy harakatga (FilledButton) yo'naltirish kerak; qolganlari pastroq urg'u bilan e'tiborni o'g'irlamasligi lozim.
β¬ οΈ Oldingi: 14 β Material 3, Cupertino va theming Β· π README Β· Keyingi: 16 β StatefulWidget va setState β‘οΈ