Adaptive Layout इंटरफ़ेस लेआउट का एक दृष्टिकोण है जिसमें एप्लिकेशन विभिन्न प्रकार के उपकरणों और स्क्रीन ओरिएंटेशन के लिए अलग-अलग लेआउट का उपयोग करता है। responsive design के विपरीत, adaptive layout ब्रेकपॉइंट बिंदुओं पर पूर्व-निर्मित लेआउट के बीच स्विच करता है। यह लेख iOS में Size Classes और UITraitCollection, Android में sw600dp/layout-w600dp क्वालिफायर और व्यावहारिक उदाहरण प्रस्तुत करता है।
मुख्य बिंदु
Adaptive Layout एक UI रणनीति है जिसमें डेवलपर प्रत्येक डिवाइस प्रकार के लिए अलग लेआउट बनाता है और स्क्रीन विशेषताओं के आधार पर उनके बीच स्विच करता है। responsive design के विपरीत जहाँ तत्व सुचारू रूप से प्रवाहित होते हैं, adaptive layout विविक्त स्विचिंग का उपयोग करता है: फ़ोन — एक लेआउट, टैबलेट — दूसरा, डेस्कटॉप — तीसरा।
Apple ने iOS 8 (2014) में यूनिवर्सल ऐप्स (iPhone और iPad दोनों पर चलने वाले बाइनरी) के साथ Size Classes पेश की। Google ने Android 3.2 (2011) में smallestWidth क्वालिफायर (sw
आधुनिक Apple HIG और Google Material Design दिशानिर्देश इस बात पर सहमत हैं कि एक से अधिक स्क्रीन आकार का समर्थन करने वाले ऐप्स के लिए adaptive layout आवश्यक है। Google Play टैबलेट अनुकूलन की कमी को कमी के रूप में चिह्नित करता है। App Store की कोई औपचारिक आवश्यकता नहीं है, लेकिन iPad उपयोगकर्ता खिंचे हुए iPhone ऐप के बजाय मूल अनुभव की अपेक्षा करते हैं।
Size Classes iOS की एक विशेषता है जो प्रत्येक अक्ष पर उपलब्ध स्थान को Compact (संकुचित) या Regular (नियमित) के रूप में परिभाषित करती है। UITraitCollection एक iOS प्रणाली है जो व्यू पदानुक्रम के माध्यम से पर्यावरण विशेषताओं को पास करती है: आकार, स्क्रीन स्केल, force touch क्षमता, रंग सरगम (हल्का/गहरा), एक्सेसिबिलिटी सेटिंग्स।
| डिवाइस / ओरिएंटेशन | क्षैतिज | लंबवत |
|---|---|---|
| iPhone पोर्ट्रेट (सभी मॉडल) | Compact | Regular |
| iPhone Plus/Pro Max लैंडस्केप | Regular | Compact |
| iPhone SE / mini लैंडस्केप | Compact | Compact |
| iPad पोर्ट्रेट | Regular | Regular |
| iPad लैंडस्केप | Regular | Regular |
| iPad Split View (1/3 स्क्रीन) | Compact | Regular |
UITraitCollection सिस्टम द्वारा बनाया जाता है और UIApplication से UIWindow के माध्यम से प्रत्येक UIView तक पहुँचाया जाता है। ओरिएंटेशन या विंडो आकार (Split View) बदलने पर सिस्टम एक नया UITraitCollection उत्पन्न करता है और traitCollectionDidChange को कॉल करता है। SwiftUI में, परिवर्तनों को Environment Values के माध्यम से ट्रैक किया जाता है और व्यू स्वचालित रूप से पुनः चित्रित होता है।
UIKit में UITraitCollection के माध्यम से अनुकूलन trait collection परिवर्तनों की सदस्यता लेकर और लेआउट को पुनर्निर्मित करके कार्यान्वित किया जाता है। नीचे दिया गया उदाहरण एक कंट्रोलर दिखाता है जो iPhone के लिए वर्टिकल स्टैक और iPad के लिए स्प्लिट लेआउट के बीच स्विच करता है।
// Size Classes के साथ अनुकूली कंट्रोलर
import UIKit
final class AdaptiveViewController: UIViewController {
private let compactStack = UIStackView()
private let regularStack = UIStackView()
private let sidebar = UIView()
private let content = UIView()
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
updateLayout(for: traitCollection)
}
override func traitCollectionDidChange(
_ previousTraitCollection: UITraitCollection?
) {
super.traitCollectionDidChange(previousTraitCollection)
if traitCollection.horizontalSizeClass
!= previousTraitCollection?.horizontalSizeClass {
updateLayout(for: traitCollection)
}
}
private func updateLayout(for traits: UITraitCollection) {
if traits.horizontalSizeClass == .regular {
showRegularLayout() // iPad: साइडबार + सामग्री
} else {
showCompactLayout() // iPhone: टैब बार + पुश
}
}
private func showRegularLayout() {
view.subviews.forEach { $0.removeFromSuperview() }
regularStack.addArrangedSubview(sidebar)
regularStack.addArrangedSubview(content)
regularStack.frame = view.bounds
regularStack.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(regularStack)
}
private func showCompactLayout() {
view.subviews.forEach { $0.removeFromSuperview() }
compactStack.addArrangedSubview(content)
compactStack.frame = view.bounds
compactStack.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(compactStack)
}
private func setupViews() {
sidebar.backgroundColor = .systemGray6
content.backgroundColor = .systemBackground
compactStack.axis = .vertical
regularStack.axis = .horizontal
}
}traitCollectionDidChange विधि किसी भी ट्रेट परिवर्तन पर कॉल की जाती है, लेकिन हम केवल horizontalSizeClass की जाँच करते हैं — लेआउट बदलने के लिए सबसे महत्वपूर्ण संकेतक। iOS 17+ में परिवर्तनों की सदस्यता लिए बिना प्रतिक्रियाशील अपडेट के लिए UIViewController.horizontalSizeClass को गणना की गई संपत्ति के रूप में उपयोग करने की अनुशंसा की जाती है।
Android दो मुख्य चौड़ाई क्वालिफायर प्रदान करता है: sw
| क्वालिफायर | शर्त | डिवाइस उदाहरण |
|---|---|---|
| layout-sw600dp | न्यूनतम चौड़ाई ≥ 600 dp | iPad (768 dp), Pixel C (900 dp) |
| layout-w600dp | वर्तमान चौड़ाई ≥ 600 dp | iPad Split View में (600 dp), लैंडस्केप में फ़ोन |
| layout-land | लैंडस्केप ओरिएंटेशन | कोई भी उपकरण क्षैतिज घुमाया गया |
| layout-sw720dp | न्यूनतम चौड़ाई ≥ 720 dp | iPad Pro (833 dp), Galaxy Tab S9 (800 dp) |
Android में संसाधन पदानुक्रम: res/layout/activity_main.xml (फ़ोन), res/layout-sw600dp/activity_main.xml (7\" टैबलेट), res/layout-w600dp-land/activity_main.xml (लैंडस्केप में फ़ोन)। Android वर्तमान डिवाइस कॉन्फ़िगरेशन से मेल खाने वाला सबसे विशिष्ट क्वालिफायर चुनता है। जब कोई मेल खाने वाली फ़ाइल नहीं होती है, तो res/layout/ से मूल संसाधन का उपयोग किया जाता है।
आधुनिक Android विकास संसाधनों को सीधे पढ़ने के बजाय विंडो आकार निर्धारित करने के लिए Jetpack WindowManager का उपयोग करता है। यह विशेष रूप से फोल्डेबल उपकरणों के लिए महत्वपूर्ण है जहाँ स्क्रीन का आकार गतिशील रूप से बदलता है (Galaxy Fold 6.2\" से 7.6\" तक खुलता है)।
// Jetpack WindowManager के माध्यम से अनुकूलन
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun AdaptiveScreen() {
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
FlowRow(
verticalAlignment = Arrangement.Top,
horizontalArrangement = when (windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.EXPANDED -> Arrangement.SpaceEvenly
else -> Arrangement.Start
}
) {
when (windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> {
CompactContent()
}
WindowWidthSizeClass.MEDIUM -> {
MediumContent()
}
WindowWidthSizeClass.EXPANDED -> {
ExpandedContent()
}
}
}
}
@Composable
private fun CompactContent() {
Column(modifier = Modifier.padding(16.dp)) {
Text("फ़ोन", style = MaterialTheme.typography.headlineSmall)
ListContent()
}
}
@Composable
private fun MediumContent() {
Row(modifier = Modifier.padding(24.dp)) {
NavigationRail { ... }
Column { ListContent() }
}
}
@Composable
private fun ExpandedContent() {
Row(modifier = Modifier.padding(32.dp)) {
PermanentNavigationDrawer { ... }
Column {
ListContent()
}
DetailPane()
}
}androidx.window लाइब्रेरी का currentWindowAdaptiveInfo() घटक किसी भी उपकरण के लिए इंटरफ़ेस को अनुकूलित करता है: फ़ोन, टैबलेट, फोल्डेबल, ChromeOS। चौड़ाई वर्ग: COMPACT (0–600 dp), MEDIUM (600–840 dp), EXPANDED (>840 dp)। ऊँचाई वर्ग: COMPACT (0–480 dp), MEDIUM (480–900 dp), EXPANDED (>900 dp)।
SwiftUI Size Classes का सीधे उपयोग किए बिना अनुकूली लेआउट के लिए अंतर्निहित उपकरण प्रदान करता है। AnyLayout, ViewThatFits और GeometryReader ऐसे इंटरफ़ेस बनाने की अनुमति देते हैं जो स्वचालित रूप से उपलब्ध स्थान के अनुकूल हो जाते हैं।
// AnyLayout और ViewThatFits के माध्यम से SwiftUI अनुकूलन
import SwiftUI
struct AdaptiveGrid: View {
@Environment(\.horizontalSizeClass) private var hSizeClass
var body: some View {
let layout = hSizeClass == .regular
? AnyLayout(HStackLayout())
: AnyLayout(VStackLayout())
layout {
Label("पसंदीदा", systemImage: "star")
Label("हाल ही के", systemImage: "clock")
Label("सेटिंग्स", systemImage: "gear")
}
.padding()
}
}
// ViewThatFits — स्वचालित लेआउट चयन
struct SmartLayout: View {
var body: some View {
ViewThatFits {
HStack { // प्राथमिकता 1: क्षैतिज
CardView()
CardView()
}
VStack { // यदि फ़िट न हो — लंबवत
CardView()
CardView()
}
}
}
}ViewThatFits एक शक्तिशाली SwiftUI उपकरण है जो स्वचालित रूप से पहली चाइल्ड व्यू का चयन करता है जो बिना क्लिपिंग के उपलब्ध स्थान में फिट बैठता है। यह सरल अनुकूली स्विचिंग के लिए Size Classes की स्पष्ट जाँच की आवश्यकता को समाप्त करता है। AnyLayout व्यू बॉडी में if-else के बिना लेआउट प्रकार (HStack/VStack) बदलने की अनुमति देता है।
Jetpack Compose अनुकूली लेआउट के लिए WindowSizeClass (Material 3 adaptive लाइब्रेरी से) और BoxWithConstraints का उपयोग करता है। XML क्वालिफायर के विपरीत, Compose रनटाइम पर विंडो आकार निर्धारित करता है और कॉन्फ़िगरेशन परिवर्तनों पर प्रतिक्रियाशील रूप से UI को पुनर्संयोजित करता है।
// BoxWithConstraints के माध्यम से Jetpack Compose अनुकूली
@Composable
fun AdaptiveList(items: List<String>) {
BoxWithConstraints {
val width = maxWidth
if (width >= 600.dp) {
// टैबलेट: दो कॉलम (list-detail)
Row(modifier = Modifier.fillMaxSize()) {
LazyColumn(modifier = Modifier.weight(1f)) {
items(items) { item ->
ListItem(text = item)
}
}
var selected by remember { mutableStateOf(items.first()) }
DetailPanel(item = selected)
.weight(2f)
}
} else {
// फ़ोन: नेविगेशन के साथ एक कॉलम
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(items) { item ->
ListItem(text = item, onClick = { navigateToDetail(item) })
}
}
}
}
}
@Composable
fun AdaptiveListMaterial3() {
val windowClass = currentWindowAdaptiveInfo().windowSizeClass
AdaptiveLayout(
layout = windowClass.windowWidthSizeClass
) {
when (windowClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> {
ListDetailScaffold(
isDetailOnly = false,
list = { ListPane() },
detail = { DetailPane() }
)
}
else -> {
ListDetailScaffold(
isDetailOnly = false,
list = { ListPane() },
detail = { DetailPane() }
)
}
}
}
}Material 3 Adaptive Layouts तैयार घटक प्रदान करते हैं: ListDetailScaffold, SupportingPaneScaffold, NavigationSuiteScaffold। ये घटक स्वचालित रूप से WindowWidthSizeClass के अनुकूल होते हैं — स्टैक्ड (COMPACT) और साइड-बाय-साइड (MEDIUM/EXPANDED) के बीच स्विच करते हैं। डेवलपर को केवल एक पैटर्न चुनना और कंटेंट पैनल पास करना होता है।
अक्सर पूछे जाने वाले प्रश्न
sw600dp (smallestWidth) — ओरिएंटेशन की परवाह किए बिना न्यूनतम स्क्रीन चौड़ाई। हमेशा 7\"+ टैबलेट पर सक्रिय होता है। w600dp (available width) — वर्तमान ओरिएंटेशन को ध्यान में रखते हुए उपलब्ध चौड़ाई। लैंडस्केप में फ़ोन पर सक्रिय होता है जहाँ चौड़ाई 600 dp से अधिक हो सकती है।
UITraitCollection एक iOS ऑब्जेक्ट है जिसमें पर्यावरण विशेषताएँ होती हैं: size classes (क्षैतिज/लंबवत), डिस्प्ले स्केल, force touch क्षमता, यूज़र इंटरफ़ेस idiom (iPhone/iPad), रंग सरगम, एक्सेसिबिलिटी सेटिंग्स। यह UIApplication से व्यू पदानुक्रम के माध्यम से पास होता है और ओरिएंटेशन या विंडो आकार बदलने पर बदलता है।
Jetpack WindowManager (Android) और UIScreen nativeBounds + traitCollection (iOS) का उपयोग करें। फोल्डेबल उपकरण खोलने पर Size Class बदलते हैं। कैनोनिकल लेआउट (list-detail, supporting pane) पर आधारित आर्किटेक्चर की सिफारिश की जाती है जिसमें Activity पुनरारंभ किए बिना विंडो आकार परिवर्तनों की प्रतिक्रियाशील सदस्यता हो।
नहीं। Size Class वेरिएशन वाले एकल storyboard या UIKit के माध्यम से प्रोग्रामेटिक लेआउट का उपयोग करें। SwiftUI को storyboards की बिल्कुल आवश्यकता नहीं है। iPad के लिए अलग storyboards दोहराव पैदा करते हैं और रखरखाव को जटिल बनाते हैं — Size Classes के माध्यम से एक लेआउट को अनुकूलित करना बेहतर है।
Canonical layouts Google द्वारा तैयार अनुकूली लेआउट पैटर्न हैं: list-detail (सूची + विवरण), supporting pane (सामग्री + क्रिया पैनल), feed (कार्ड)। प्रत्येक पैटर्न तीन स्थितियों (compact/medium/expanded) का समर्थन करता है और Material 3 Adaptive लाइब्रेरी में ListDetailScaffold और SupportingPaneScaffold के माध्यम से कार्यान्वित किया गया है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें