Theory
छह Tickets, एक Thumb
Group bookings आती हैं: per student 6 tickets तक। "six" और "6six" accept करने वाला एक TextField पुराना pain है; natural control एक slider है जिसका thumb 1 से 6 तक drag होता है।
आप Slider को इसके min और max के साथ wire करते हैं, इसे चलाते हैं, drag करते हैं: और thumb हर बार वापस 1 पर snap करता है। Broken नहीं: Flutter आपको अपनी single most important interaction law सिखा रहा है, और यह lesson इसे properly सीखने के around built है: button family को इसकी ranks मिलने के ठीक बाद।
Theory
Button Family, Rank से
सभी buttons same heart share करते हैं (onPressed + child, null disables): जो अलग है वह है visual rank:
- ElevatedButton: raised, filled: primary action (Book)
- OutlinedButton: bordered: middle-rank actions (Add to wishlist)
- TextButton: flat text: secondary, low-noise (Cancel, Skip)
- IconButton: icon-only, compact: toolbars (share, favourite)
- FloatingActionButton: round floating वाला, Scaffold के अपने
floatingActionButton:slot में रहता है: per screen एक, इसकी defining action
Rank = visual loudness = importance: per region एक Elevated, इसके बगल में quiet Texts।
Practical
Quantity Slider, सही तरीके से
class _BookingState extends State<BookingScreen> {
double tickets = 1; // the STATE owns the value
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Tickets: ${tickets.toInt()}'),
Slider(
value: tickets, // slider DISPLAYS the state
min: 1,
max: 6,
divisions: 5, // discrete stops: 1,2,3,4,5,6
label: '${tickets.toInt()}', // bubble at the thumb
onChanged: (v) {
setState(() { tickets = v; }); // no setState = snap-back
},
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(onPressed: () {}, child: const Text('Cancel')),
ElevatedButton(
onPressed: () { /* book tickets.toInt() seats */ },
child: const Text('Book'),
),
],
),
],
);
}
}
Theory
Controlled-Widget Law
Naked slider वापस snap क्यों हुआ? क्योंकि एक Flutter Slider अपनी position खुद नहीं रखता। Listing का loop पढ़िए:
value: tickets: slider जो भी state variable hold करता है वह DISPLAY करता है- dragging
onChanged(v)fire करता है CANDIDATE value के साथ: continuously, पूरे drag के दौरान - आपका handler variable को setState करता है: build फिर चलता है: slider अब नई value display करता है
setState skip कीजिए और variable कभी नहीं बदलता, तो हर rebuild thumb को पुरानी value पर repaint करता है: snap-back। Widget state का एक view है, कभी इसका keeper नहीं: और Checkbox, Radio और Switch, अगले lessons में wait करते हुए, identical law obey करते हैं।
Quiz
एक Slider में correct min, max और value है, और onChanged: (v) { tickets = v; } setState के WITHOUT। User क्या experience करता है?
- Slider काम करता है: आख़िरकार variable update हो रहा है
- हर drag पर thumb वापस snap होता है: variable बदलता है पर कोई rebuild इसके साथ slider repaint नहीं करता
- एक compile error: onChanged को setState call करना ज़रूरी है
- Slider move करता है पर Text label एक drag पीछे lag करता है
Show the answer
हर drag पर thumb वापस snap होता है: variable बदलता है पर कोई rebuild इसके साथ slider repaint नहीं करता
Variable असल में बदलता है (option A का grain of truth): पर screen सिर्फ़ rebuild पर repaint होती है, और सिर्फ़ setState एक schedule करता है: तो slider... कुछ भी नहीं से rebuild होता रहता है, क्योंकि कोई rebuild नहीं होता: यह drag gesture के अगले frame पर पुरानी position पर repaint होता है, snapping back। यह controlled-widget law एक bug में है: widgets state display करते हैं; setState changes publish करता है। Option C: compiler आपका intent नहीं जान सकता: यह एक logic bug है, worst kind। Option D एक subtler staleness describe करता है जो दूसरी mistakes की वजह से होती है: यह total है।
Think first
Screen के Buttons को Rank कीजिए
Booking screen को चाहिए: Book (screen का point), Cancel, एक heart icon wishlist के लिए, और पूरी event list पर visible एक screen-wide New Booking action। हर एक को इसका button variant assign कीजिए ranking reason के साथ, फिर tap कीजिए।
Show the answer
Book: ElevatedButton: per region एक loud primary। Cancel: TextButton: present पर quiet, कभी Book से compete नहीं करता (listing उन्हें exactly इसी तरह place करती है)। Wishlist heart: IconButton: compact, recognisable, toolbar-grade। List पर New Booking: Scaffold slot में FloatingActionButton: Material convention से THE screen action (WhatsApp के compose button की तरह सोचिए)। Principle: visual loudness importance से match होनी चाहिए: side by side 2 Elevated buttons एक shouting match है, और exams यह कहने के लिए reward देते हैं।
Watch out
Slider और Button Slips
Slider Value एक Double है: इसे raw display करना 3.0 tickets दिखाता है: humans के लिए .toInt() (listing दो बार करती है)।
Divisions Off By One: stops = divisions + 1: range 1 से 6 को divisions: 5 चाहिए: फिर वही fencepost।
onChanged Drag के दौरान Fire होता है: continuously, release पर एक बार नहीं: वहाँ heavy work gesture को stutter करता है (TextWatcher lesson का rule, तीसरी appearance)।
दो FABs: Scaffold slot एक लेता है; एक second floating action एक parameter नहीं, एक design smell है।
Theory
एक Law, चार Widgets आगे
Controlled-widget law एक बार frame कीजिए और इसे lit रखिए: state से value, onChanged + setState से change, widget कभी अपना score नहीं रखता। अगले lesson का Checkbox और Radio यही law verbatim हैं (Radio exclusivity पर एक clever twist add करता है जिसे BCA404 के GroupBox veterans compare करना चाहेंगे), और Unit 5 का Switch इसे फिर है। यहाँ loop सीखिए, 3 बार और marks collect कीजिए।
Summary
Key takeaways
- Button ranks: ElevatedButton primary, OutlinedButton middle, TextButton quiet, IconButton compact, THE screen action के लिए Scaffold के slot में FAB।
- सभी onPressed (null = disabled) + child share करते हैं; loudness importance से match होनी चाहिए।
- Slider(value, min, max, divisions, label, onChanged): value एक double है जो STATE owns करता है।
- Controlled-widget law: widget state display करता है; onChanged + setState changes publish करते हैं; बिना setState thumb snap back होता है।
- divisions + 1 = stops; label thumb पर bubble करता है; onChanged drag के दौरान continuously fire होता है।
- वही law Checkbox, Radio और Switch को अगली बार govern करता है।
- Memory hook: widgets score दिखाते हैं, setState इसे लिखता है।