फ़ोल्ड किए गए डिवाइसों पर, बड़े डिसप्ले और फ़ोल्ड किए गए डिवाइसों के अलग-अलग स्टेटस की मदद से, उपयोगकर्ताओं को नया अनुभव मिलता है. अपने ऐप्लिकेशन को फ़ोल्ड करने की जानकारी देने के लिए, Jetpack WindowManager लाइब्रेरी का इस्तेमाल करें. यह डिवाइस की विंडो को फ़ोल्ड और हिंज जैसी सुविधाओं के लिए एपीआई सरफ़ेस उपलब्ध कराता है. जब आपका ऐप्लिकेशन फ़ोल्ड के बारे में जानता है, तो वह अपने लेआउट को अडजस्ट कर सकता है, ताकि फ़ोल्ड या हिंज वाले हिस्से में ज़रूरी कॉन्टेंट न रखा जाए. साथ ही, फ़ोल्ड और हिंज का इस्तेमाल, कॉन्टेंट को अलग करने के लिए किया जा सकता है.
यह समझने से कि कोई डिवाइस, टेबलटॉप या किताब के तौर पर इस्तेमाल करने जैसे कॉन्फ़िगरेशन के साथ काम करता है या नहीं, अलग-अलग लेआउट इस्तेमाल करने या खास सुविधाएं देने के बारे में फ़ैसले लिए जा सकते हैं.
विंडो की जानकारी
Jetpack WindowManager में WindowInfoTracker
इंटरफ़ेस, विंडो के लेआउट की जानकारी दिखाता है. इंटरफ़ेस का windowLayoutInfo()
तरीका, WindowLayoutInfo
डेटा की स्ट्रीम दिखाता है. इससे आपके ऐप्लिकेशन को फ़ोल्ड किए जा सकने वाले डिवाइस की फ़ोल्ड की गई स्थिति के बारे में पता चलता है. WindowInfoTracker#getOrCreate()
तरीका, WindowInfoTracker
का एक उदाहरण बनाता है.
WindowManager, Kotlin फ़्लो और Java कॉलबैक का इस्तेमाल करके,
WindowLayoutInfo
का डेटा इकट्ठा करने में मदद करता है.
Kotlin फ़्लो
WindowLayoutInfo
डेटा कलेक्शन को शुरू और बंद करने के लिए, फिर से शुरू किए जा सकने वाले, लाइफ़साइकल के बारे में जानकारी रखने वाले कोरुटाइन का इस्तेमाल किया जा सकता है. इसमें, लाइफ़साइकल कम से कम STARTED
होने पर repeatOnLifecycle
कोड ब्लॉक को शुरू किया जाता है और लाइफ़साइकल STOPPED
होने पर उसे बंद कर दिया जाता है. लाइफ़साइकल फिर से STARTED
होने पर, कोड ब्लॉक का एक्सीक्यूशन अपने-आप फिर से शुरू हो जाता है. नीचे दिए गए उदाहरण में, कोड ब्लॉक WindowLayoutInfo
डेटा इकट्ठा करता है और उसका इस्तेमाल करता है:
class DisplayFeaturesActivity : AppCompatActivity() {
private lateinit var binding: ActivityDisplayFeaturesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDisplayFeaturesBinding.inflate(layoutInflater)
setContentView(binding.root)
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 = ActivitySplitLayoutBinding.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
एलिमेंट की सूची के तौर पर उपलब्ध कराती है.
FoldingFeature
एक तरह का DisplayFeature
है, जो फ़ोल्ड किए जा सकने वाले डिसप्ले के बारे में जानकारी देता है. इसमें यह जानकारी शामिल है:
state
: डिवाइस की फ़ोल्ड की गई स्थिति,FLAT
याHALF_OPENED
orientation
: फ़ोल्ड या हिंज का ओरिएंटेशन,HORIZONTAL
याVERTICAL
occlusionType
: क्या फ़ोल्ड या हिंज, डिसप्ले के कुछ हिस्से को छिपा देता है,NONE
याFULL
isSeparating
: क्या फ़ोल्ड या हिंज दो लॉजिकल डिसप्ले एरिया बनाता है, सही या गलत
फ़ोल्ड किए जा सकने वाला ऐसा डिवाइस जो 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().extensionsVersion >= 6) { val postures = WindowInfoTracker.getOrCreate(context).supportedPostures if (postures.contains(TABLE_TOP)) { // 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 की मदद से, फ़ोल्ड किए जा सकने वाले डिवाइसों पर कैमरा ऐप्लिकेशन को ऑप्टिमाइज़ करना