फ़ोल्ड किए जा सकने वाले डिवाइसों पर, बड़ी अनफ़ोल्ड स्क्रीन और फ़ोल्ड किए जाने की अलग-अलग स्थितियों की वजह से, उपयोगकर्ताओं को नया अनुभव मिलता है. अपने ऐप्लिकेशन को फ़ोल्ड किए जा सकने वाले डिवाइसों के हिसाब से बनाने के लिए, Jetpack WindowManager लाइब्रेरी का इस्तेमाल करें. यह लाइब्रेरी, फ़ोल्ड किए जा सकने वाले डिवाइसों की विंडो से जुड़ी सुविधाओं के लिए एपीआई उपलब्ध कराती है. जैसे, फ़ोल्ड और हिंज. अगर आपका ऐप्लिकेशन, फ़ोल्ड किए जा सकने वाले डिवाइसों के हिसाब से बना है, तो वह अपने लेआउट को इस तरह से अडजस्ट कर सकता है कि अहम कॉन्टेंट, फ़ोल्ड या हिंज वाली जगह पर न दिखे. साथ ही, फ़ोल्ड और हिंज को नैचुरल सेपरेटर के तौर पर इस्तेमाल किया जा सकता है.
यह समझने से कि कोई डिवाइस, टेबलटॉप या बुक पोस्चर जैसे कॉन्फ़िगरेशन के साथ काम करता है या नहीं, अलग-अलग लेआउट के साथ काम करने या खास सुविधाएं उपलब्ध कराने के बारे में फ़ैसले लेने में मदद मिल सकती है.
विंडो की जानकारी
Jetpack WindowManager में मौजूद WindowInfoTracker इंटरफ़ेस, विंडो
के लेआउट की जानकारी दिखाता है. इंटरफ़ेस का windowLayoutInfo() तरीका,
WindowLayoutInfo डेटा की एक स्ट्रीम दिखाता है. इससे आपके ऐप्लिकेशन को, फ़ोल्ड किए जा सकने वाले
डिवाइस के फ़ोल्ड की स्थिति के बारे में पता चलता है. The WindowInfoTracker#getOrCreate() तरीका, एक
इंस्टेंस बनाता है WindowInfoTracker.
WindowManager, Kotlin फ़्लो और Java कॉलबैक का इस्तेमाल करके, WindowLayoutInfo डेटा इकट्ठा करने की सुविधा देता है.
Kotlin फ़्लो
WindowLayoutInfo डेटा कलेक्शन को शुरू और बंद करने के लिए, रीस्टार्ट किए जा सकने वाले
लाइफ़साइकल-अवेयर कोरोटीन का इस्तेमाल किया जा सकता है. इसमें, repeatOnLifecycle कोड ब्लॉक तब
एक्ज़ीक्यूट होता है, जब लाइफ़साइकल कम से कम STARTED पर हो. साथ ही, जब
लाइफ़साइकल STOPPED पर होता है, तब यह बंद हो जाता है. जब लाइफ़साइकल फिर से STARTED पर होता है, तो कोड ब्लॉक का एक्ज़ीक्यूशन अपने-आप रीस्टार्ट हो जाता है. यहां दिए गए उदाहरण में, कोड ब्लॉक WindowLayoutInfo डेटा इकट्ठा करता है और उसका इस्तेमाल करता है:
class DisplayFeaturesActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { // ... lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { WindowInfoTracker.getOrCreate(this@DisplayFeaturesActivity) .windowLayoutInfo(this@DisplayFeaturesActivity) .collect { newLayoutInfo -> // Use newLayoutInfo to update the layout. } } } } }
Java कॉलबैक
androidx.window:window-java डिपेंडेंसी में शामिल कॉलबैक कंपैटबिलिटी लेयर की मदद से, Kotlin फ़्लो का इस्तेमाल किए बिना,
WindowLayoutInfo के अपडेट इकट्ठा किए जा सकते हैं. आर्टफ़ैक्ट में
WindowInfoTrackerCallbackAdapter क्लास शामिल होती है. यह क्लास, WindowInfoTracker को अडजस्ट करती है, ताकि
WindowLayoutInfo के अपडेट पाने के लिए कॉलबैक रजिस्टर (और अनरजिस्टर) किए जा सकें. उदाहरण के लिए:
public class SplitLayoutActivity extends AppCompatActivity {
private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private ActivitySplitLayoutBinding binding;
private final LayoutStateChangeCallback layoutStateChangeCallback =
new LayoutStateChangeCallback();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
windowInfoTracker =
new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}
@Override
protected void onStart() {
super.onStart();
windowInfoTracker.addWindowLayoutInfoListener(
this, Runnable::run, layoutStateChangeCallback);
}
@Override
protected void onStop() {
super.onStop();
windowInfoTracker
.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}
class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
@Override
public void accept(WindowLayoutInfo newLayoutInfo) {
SplitLayoutActivity.this.runOnUiThread( () -> {
// Use newLayoutInfo to update the layout.
});
}
}
}
RxJava की सुविधा
अगर आपने RxJava (वर्शन 2 या 3) का इस्तेमाल पहले से किया है, तो ऐसे आर्टफ़ैक्ट का फ़ायदा लिया जा सकता है जिनकी मदद से, Kotlin फ़्लो का इस्तेमाल किए बिना, WindowLayoutInfo के अपडेट इकट्ठा करने के लिए Observable या Flowable का इस्तेमाल किया जा सकता है.
androidx.window:window-rxjava2 और
androidx.window:window-rxjava3 डिपेंडेंसी से मिली कंपैटबिलिटी लेयर में, WindowInfoTracker#windowLayoutInfoFlowable() और
WindowInfoTracker#windowLayoutInfoObservable() तरीके शामिल होते हैं. इनकी मदद से, आपका
ऐप्लिकेशन WindowLayoutInfo के अपडेट पा सकता है. उदाहरण के लिए:
class RxActivity: AppCompatActivity {
private lateinit var binding: ActivityRxBinding
private var disposable: Disposable? = null
private lateinit var observable: Observable<WindowLayoutInfo>
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityRxBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Create a new observable.
observable = WindowInfoTracker.getOrCreate(this@RxActivity)
.windowLayoutInfoObservable(this@RxActivity)
}
@Override
protected void onStart() {
super.onStart();
// Subscribe to receive WindowLayoutInfo updates.
disposable?.dispose()
disposable = observable
.observeOn(AndroidSchedulers.mainThread())
.subscribe { newLayoutInfo ->
// Use newLayoutInfo to update the layout.
}
}
@Override
protected void onStop() {
super.onStop();
// Dispose of the WindowLayoutInfo observable.
disposable?.dispose()
}
}
फ़ोल्ड किए जा सकने वाले डिसप्ले की सुविधाएं
Jetpack WindowManager की WindowLayoutInfo क्लास, डिसप्ले विंडो की सुविधाओं को DisplayFeature एलिमेंट की सूची के तौर पर उपलब्ध कराती है.
A FoldingFeature, DisplayFeature का एक टाइप है. यह फ़ोल्ड किए जा सकने वाले डिसप्ले के बारे में जानकारी
देता है. इसमें ये प्रॉपर्टी शामिल हैं:
state: डिवाइस की फ़ोल्ड की स्थिति,FLATयाHALF_OPENEDorientation: फ़ोल्ड या हिंज का ओरिएंटेशन,HORIZONTALयाVERTICALocclusionType: फ़ोल्ड या हिंज, डिसप्ले के किसी हिस्से को छिपाता है या नहीं,NONEयाFULLisSeparating: फ़ोल्ड या हिंज, डिसप्ले के दो लॉजिकल एरिया बनाता है या नहीं, सही या गलत
HALF_OPENED स्थिति में मौजूद फ़ोल्ड किए जा सकने वाले डिवाइस के लिए, isSeparating की वैल्यू हमेशा 'सही' होती है. ऐसा इसलिए, क्योंकि स्क्रीन को डिसप्ले के दो एरिया में बांटा जाता है. साथ ही, ड्यूअल‑स्क्रीन वाले डिवाइस पर, isSeparating की वैल्यू हमेशा 'सही' होती है. ऐसा तब होता है, जब ऐप्लिकेशन दोनों स्क्रीन पर दिखता है.
FoldingFeature bounds प्रॉपर्टी (जो DisplayFeature से इनहेरिट की गई है)
फ़ोल्ड या हिंज जैसी फ़ोल्ड करने की सुविधा के बाउंडिंग रेक्टैंगल को दिखाती है.
बाउंड का इस्तेमाल, स्क्रीन पर एलिमेंट को सुविधा के हिसाब से पोज़िशन करने के लिए किया जा सकता है:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { // ... lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { // Safely collects from WindowInfoTracker when the lifecycle is // STARTED and stops collection when the lifecycle is STOPPED. WindowInfoTracker.getOrCreate(this@MainActivity) .windowLayoutInfo(this@MainActivity) .collect { layoutInfo -> // New posture information. val foldingFeature = layoutInfo.displayFeatures .filterIsInstance<FoldingFeature>() .firstOrNull() // Use information from the foldingFeature object. } } } }
Java
private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private final LayoutStateChangeCallback layoutStateChangeCallback =
new LayoutStateChangeCallback();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// ...
windowInfoTracker =
new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}
@Override
protected void onStart() {
super.onStart();
windowInfoTracker.addWindowLayoutInfoListener(
this, Runnable::run, layoutStateChangeCallback);
}
@Override
protected void onStop() {
super.onStop();
windowInfoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}
class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
@Override
public void accept(WindowLayoutInfo newLayoutInfo) {
// Use newLayoutInfo to update the Layout.
List<DisplayFeature> displayFeatures = newLayoutInfo.getDisplayFeatures();
for (DisplayFeature feature : displayFeatures) {
if (feature instanceof FoldingFeature) {
// Use information from the feature object.
}
}
}
}
टेबलटॉप पोस्चर
FoldingFeature ऑब्जेक्ट में शामिल जानकारी का इस्तेमाल करके, आपका ऐप्लिकेशन टेबलटॉप जैसे पोस्चर के साथ काम कर सकता है. इसमें फ़ोन किसी जगह पर रखा जाता है, हिंज हॉरिज़ॉन्टल पोज़िशन में होता है, और फ़ोल्ड की जा सकने वाली स्क्रीन आधी खुली होती है.
टेबलटॉप पोस्चर की मदद से, उपयोगकर्ता अपने फ़ोन को हाथ में लिए बिना इस्तेमाल कर सकते हैं. टेबलटॉप पोस्चर, मीडिया देखने, फ़ोटो लेने, और वीडियो कॉल करने के लिए बहुत अच्छा है.
यह पता लगाने के लिए कि डिवाइस टेबलटॉप पोस्चर में है या नहीं, FoldingFeature.State और FoldingFeature.Orientation का इस्तेमाल करें:
Kotlin
fun isTableTopPosture(foldFeature: FoldingFeature?): Boolean { contract { returns(true) implies (foldFeature != null) } return foldFeature?.state == FoldingFeature.State.HALF_OPENED && foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL }
Java
boolean isTableTopPosture(FoldingFeature foldFeature) {
return (foldFeature != null) &&
(foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
(foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL);
}
यह पता चलने पर कि डिवाइस टेबलटॉप पोस्चर में है, अपने ऐप्लिकेशन के लेआउट को उसके हिसाब से अपडेट करें. मीडिया ऐप्लिकेशन के लिए, इसका आम तौर पर मतलब होता है कि प्लेबैक को फ़ोल्ड के ऊपर रखा जाए. साथ ही, कंट्रोल और सप्लीमेंट्री कॉन्टेंट को, हाथ का इस्तेमाल किए बिना वीडियो देखने या ऑडियो सुनने के अनुभव के लिए, ठीक उसके बाद पोज़िशन किया जाए.
Android 15 (एपीआई लेवल 35) और उसके बाद के वर्शन पर, सिंक एपीआई को कॉल करके यह पता लगाया जा सकता है कि कोई डिवाइस टेबलटॉप पोस्चर के साथ काम करता है या नहीं. भले ही, डिवाइस की मौजूदा स्थिति कुछ भी हो.
एपीआई, डिवाइस के साथ काम करने वाले पोस्चर की सूची उपलब्ध कराता है. अगर सूची में टेबलटॉप पोस्चर शामिल है, तो अपने ऐप्लिकेशन के लेआउट को स्प्लिट करके, इस पोस्चर के साथ काम करने की सुविधा दी जा सकती है. साथ ही, टेबलटॉप और फ़ुल‑स्क्रीन लेआउट के लिए, अपने ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) पर A/B टेस्ट किए जा सकते हैं.
Kotlin
if (WindowSdkExtensions.getInstance().extensionVersion >= 6) { val postures = WindowInfoTracker.getOrCreate(context).supportedPostures if (postures.contains(SupportedPosture.TABLETOP)) { // Device supports tabletop posture. } }
Java
if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
List<SupportedPosture> postures = WindowInfoTracker.getOrCreate(context).getSupportedPostures();
if (postures.contains(SupportedPosture.TABLETOP)) {
// Device supports tabletop posture.
}
}
उदाहरण
MediaPlayerActivityऐप्लिकेशन: फ़ोल्ड किए जा सकने वाले डिवाइसों के हिसाब से वीडियो प्लेयर बनाने के लिए, Media3 Exoplayer और WindowManager का इस्तेमाल करने का तरीका जानें.Jetpack WindowManager कोडलैब की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइसों पर अपने कैमरा ऐप्लिकेशन को ऑप्टिमाइज़ करें: फ़ोटोग्राफ़ी ऐप्लिकेशन के लिए, टेबलटॉप पोस्चर लागू करने का तरीका जानें. व्यूफ़ाइंडर को स्क्रीन के ऊपरी हिस्से (फ़ोल्ड के ऊपर) और कंट्रोल को निचले हिस्से (फ़ोल्ड के नीचे) पर दिखाएं.
बुक पोस्चर
फ़ोल्ड किए जा सकने वाले डिवाइसों की एक और खास सुविधा है बुक पोस्चर. इसमें डिवाइस आधा खुला होता है और हिंज वर्टिकल होता है. बुक पोस्चर, ई‑बुक पढ़ने के लिए बहुत अच्छा है. बड़ी स्क्रीन वाले फ़ोल्ड किए जा सकने वाले डिवाइस पर, दो‑पेज लेआउट के साथ, बुक पोस्चर से असली किताब पढ़ने का अनुभव मिलता है.
इसका इस्तेमाल फ़ोटोग्राफ़ी के लिए भी किया जा सकता है. अगर आपको हाथ का इस्तेमाल किए बिना फ़ोटो लेते समय, अलग-अलग आसपेक्ट रेशियो कैप्चर करना है.
बुक पोस्चर को लागू करने के लिए, टेबलटॉप पोस्चर के लिए इस्तेमाल की जाने वाली तकनीकों का ही इस्तेमाल करें. फ़र्क़ सिर्फ़ इतना है कि कोड को यह जांच करनी चाहिए कि फ़ोल्ड करने की सुविधा का ओरिएंटेशन हॉरिज़ॉन्टल के बजाय वर्टिकल है या नहीं:
Kotlin
fun isBookPosture(foldFeature: FoldingFeature?): Boolean { contract { returns(true) implies (foldFeature != null) } return foldFeature?.state == FoldingFeature.State.HALF_OPENED && foldFeature.orientation == FoldingFeature.Orientation.VERTICAL }
Java
boolean isBookPosture(FoldingFeature foldFeature) {
return (foldFeature != null) &&
(foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
(foldFeature.getOrientation() == FoldingFeature.Orientation.VERTICAL);
}
विंडो के साइज़ में बदलाव
डिवाइस के कॉन्फ़िगरेशन में बदलाव होने की वजह से, किसी ऐप्लिकेशन का डिसप्ले एरिया बदल सकता है. उदाहरण के लिए, जब डिवाइस को फ़ोल्ड या अनफ़ोल्ड किया जाता है, घुमाया जाता है या मल्टी‑विंडो मोड में किसी विंडो का साइज़ बदला जाता है.
Jetpack WindowManager की WindowMetricsCalculator क्लास की मदद से, विंडो की मौजूदा और ज़्यादा से ज़्यादा मेट्रिक वापस पाई जा सकती हैं. एपीआई लेवल 30 में पेश किए गए प्लैटफ़ॉर्म
WindowMetrics की तरह, WindowManager
WindowMetrics भी विंडो के बाउंड उपलब्ध कराता है. हालांकि, यह एपीआई, एपीआई लेवल 14 तक के वर्शन के साथ काम करता है.
विंडो के साइज़ की क्लास का इस्तेमाल करना लेख पढ़ें.
अन्य संसाधन
सैंपल
- Jetpack WindowManager: Jetpack WindowManager लाइब्रेरी का इस्तेमाल करने का तरीका
- Jetcaster : Compose की मदद से, टेबलटॉप पोस्चर लागू करना
कोडलैब
- Jetpack WindowManager की मदद से, फ़ोल्ड किए जा सकने वाले और ड्यूअल-स्क्रीन डिवाइस बनाएं
- Jetpack WindowManager की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइसों पर अपने कैमरा ऐप्लिकेशन को ऑप्टिमाइज़ करें