Theory
एक Phone के लिए लड़ती तीन Screens
FestConnect Mobile अब एक event list, एक schedule और student के pass का owner है: content की 3 पूरी screens और एक committee जो चाहती है सब "one tap away, no back button"।
जो app आप रोज़ इस्तेमाल करते हैं उसने यह same तरीके से solve किया: एक tab strip: WhatsApp का Chats/Status/Calls, और अब आपका Events/Schedule/My Pass।
Android इस काम को 2 widgets के बीच split करता है: एक strip draw और manage करता है, और एक, SDK का सबसे humble container, वह stage hold करता है जो वे share करते हैं।
Theory
FrameLayout: Transparencies का Stack
एक FrameLayout लगभग कुछ नहीं करता, जो इसका genius है: children rows या columns में arranged नहीं होते: वे एक frame में stack करते हैं, हर एक पिछले के ऊपर drawn: तो XML का last child ऊपर बैठता है।
दो jobs इससे निकलते हैं:
- overlays: एक "SOLD OUT" banner child एक poster child के ऊपर drawn:
layout_gravityसे frame के अंदर children place कीजिए - एक swappable stage: सारी 3 section views को एक FrameLayout के अंदर रखिए और एक बार में ONE दिखाइए: tab pattern का दूसरा आधा
Theory
TabLayout: Strip जो Decide करता है
TabLayout (Material library से) tab strip और इसकी ink-bar animation render करता है। दोनों तरीकों से tabs बनाइए:
tabs.addTab(tabs.newTab().setText("Events"));
या <TabItem> children की तरह XML में। फिर listen कीजिए:
tabs.addOnTabSelectedListener(...) 3 callbacks के साथ: onTabSelected (एक नया tab चुना गया: यहाँ act कीजिए, tab.getPosition() बताता है कौन सा), onTabUnselected (पुराना वाला focus खो रहा है), onTabReselected (current tab फिर tap करना: apps अक्सर यहाँ scroll-to-top करते हैं)।
Strip DECIDE करता है; कुछ और DISPLAY करना चाहिए: enter FrameLayout।
Practical
Frame के Visible Child को Switch करते Tabs
public class MainActivity extends AppCompatActivity {
View eventsView, scheduleView, passView;
@Override
protected void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_main); // TabLayout over FrameLayout
eventsView = findViewById(R.id.sectionEvents);
scheduleView = findViewById(R.id.sectionSchedule);
passView = findViewById(R.id.sectionPass);
TabLayout tabs = findViewById(R.id.tabs);
tabs.addTab(tabs.newTab().setText("Events"));
tabs.addTab(tabs.newTab().setText("Schedule"));
tabs.addTab(tabs.newTab().setText("My Pass"));
tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override public void onTabSelected(TabLayout.Tab tab) {
eventsView.setVisibility(tab.getPosition() == 0 ? View.VISIBLE : View.GONE);
scheduleView.setVisibility(tab.getPosition() == 1 ? View.VISIBLE : View.GONE);
passView.setVisibility(tab.getPosition() == 2 ? View.VISIBLE : View.GONE);
}
@Override public void onTabUnselected(TabLayout.Tab tab) { }
@Override public void onTabReselected(TabLayout.Tab tab) { }
});
}
}
Quiz
एक FrameLayout XML में पहले एक ImageView (poster) hold करता है, फिर एक TextView ("SOLD OUT")। User क्या देखता है?
- Poster text के ऊपर, LinearLayout की तरह vertically stacked
- SOLD OUT text poster के ऊपर drawn: FrameLayout children stack करता है, last child ऊपर
- सिर्फ़ poster: एक FrameLayout सिर्फ़ अपना पहला child दिखाता है
- एक crash: FrameLayout, ScrollView की तरह, सिर्फ़ एक child allow करता है
Show the answer
SOLD OUT text poster के ऊपर drawn: FrameLayout children stack करता है, last child ऊपर
FrameLayout transparencies का stack है: हर child same frame occupy करता है, XML order में painted होता है, तो बाद वाला TextView poster को overlay करता है: exactly ऐसे ही badges, watermarks और sold-out banners बनते हैं। Option A LinearLayout की row-stacking import करता है: वह arranging container जो यह deliberately नहीं है। Option C इसे एक ViewSwitcher-style widget से confuse करता है: सारे children drawn होते हैं, visibility permitting। Option D 3 lessons पहले का ScrollView one-child law borrow करता है: FrameLayout कई children happily accept करता है: overlap इसका feature है, failure नहीं।
Think first
GONE क्यों, और Reselect किसके लिए है?
Listing की 2 design readings: (a) hidden sections View.INVISIBLE की बजाय View.GONE इस्तेमाल करते हैं: फ़र्क क्या है और GONE यहाँ क्यों fit करता है? (b) आप actually onTabReselected में code कब लिखेंगे? सोचिए, फिर tap कीजिए।
Show the answer
(a) INVISIBLE एक view छुपाता है पर layout में इसकी space reserved रहती है; GONE इसे layout से पूरी तरह हटाता है, जैसे यह absent हो। Stacked full-screen sections को GONE चाहिए: कुछ भी ghost space hold नहीं करना चाहिए (एक FrameLayout के अंदर दोनों children वैसे भी overlap करते हैं, पर GONE hidden views को touches intercept करने और measured होने से भी रोकता है)। (b) onTabReselected तब fire होता है जब CURRENT tab फिर tap हो: polished-app convention scroll-to-top या refresh है: WhatsApp के Chats tab को पहले से उस पर होते हुए tap करने के बारे में सोचिए। सभी 3 callbacks की jobs जानना tabs को wire करने और उन्हें समझने के बीच का फ़र्क है।
Watch out
Tab Traps
Launch पर कुछ नहीं दिखता: listener SELECTION CHANGES पर fire होता है: initial visibilities set कीजिए (या tab 0 को programmatically select कीजिए) वरना frame empty या overlapping शुरू होता है।
सभी 3 Methods Compulsory हैं: OnTabSelectedListener एक interface है: unused वालों के लिए empty bodies, वरना compile नहीं होगा (फिर वही TextWatcher rule)।
Heavy Views Alive रखी जाती हैं: इस pattern के साथ सभी 3 sections memory में exist करती हैं: 3 के लिए fine, 10 के लिए wasteful: यही वजह है production TabLayout को ViewPager2 + fragments के साथ pair करती है, वह beyond-syllabus upgrade जो एक exam footnote में नाम देने लायक है।
Theory
Unit 1 बंद होती है: Android का आधा Done है
FestConnect Mobile अब scroll करती है, richly list करती है, dates पिक करती है, search suggest करती है, posters slide करती है और खुद को tabs में organise करती है: Java + XML में एक real app की widget vocabulary, सब। इस ridge पर एक breath लीजिए: subject अब LANGUAGE बदलता है। Unit 2 Dart introduce करती है, Unit 3 Flutter, और Unit 5 तक आप इसी screen को rebuild करेंगे: वही app, नई universe: test कि आपने patterns सीखे या सिर्फ़ syntax।
Summary
Key takeaways
- FrameLayout children को एक frame में stack करता है, XML order bottom-to-top: overlays और swappable stages।
- layout_gravity frame के अंदर एक child position करता है; GONE layout से remove करता है, INVISIBLE सिर्फ़ hide करता है।
- TabLayout strip draw करता है: addTab(newTab().setText(...)), addOnTabSelectedListener से listen कीजिए।
- तीन callbacks: onTabSelected (act, getPosition से), onTabUnselected, onTabReselected (scroll-to-top convention)।
- Syllabus pattern: tabs decide करते हैं, FrameLayout display करता है: position के हिसाब से child visibility switch कीजिए।
- Initial visibility खुद set कीजिए; production-scale apps ViewPager2 + fragments में upgrade होते हैं।
- Memory hook: strip decide करता है, frame display करता है, last child ऊपर।