डेस्कटॉप विंडोिंग का समर्थन

डेस्कटॉप विंडोविंग की मदद से, उपयोगकर्ता एक साथ कई ऐप्लिकेशन चला सकते हैं. इसके लिए, वे ऐप्लिकेशन विंडो का साइज़ बदल सकते हैं. इससे उन्हें डेस्कटॉप जैसा अनुभव मिलता है.

पहली इमेज में, डेस्कटॉप विंडोविंग की सुविधा चालू होने पर स्क्रीन का लेआउट दिखाया गया है. इन बातों का ध्यान रखें:

  • उपयोगकर्ता, एक साथ कई ऐप्लिकेशन को साइड-बाय-साइड चला सकते हैं.
  • टास्कबार, डिसप्ले के सबसे नीचे एक ही जगह पर मौजूद है. इसमें चालू ऐप्लिकेशन दिख रहे हैं. उपयोगकर्ता, ऐप्लिकेशन को पिन कर सकते हैं, ताकि उन्हें तुरंत ऐक्सेस किया जा सके.
  • पसंद के मुताबिक बनाए जा सकने वाले नए हेडर बार में, हर विंडो के सबसे ऊपर कंट्रोल दिए गए हैं. जैसे, छोटा और बड़ा करें.
पहली इमेज. टैबलेट पर डेस्कटॉप विंडोइंग की सुविधा.

डिफ़ॉल्ट रूप से, Android टैबलेट पर ऐप्लिकेशन फ़ुल स्क्रीन में खुलते हैं. डेस्कटॉप विंडोविंग मोड में किसी ऐप्लिकेशन को लॉन्च करने के लिए, स्क्रीन पर सबसे ऊपर मौजूद विंडो हैंडल को दबाकर रखें. इसके बाद, हैंडल को यूज़र इंटरफ़ेस (यूआई) में खींचें. जैसा कि इमेज 2 में दिखाया गया है.

जब कोई ऐप्लिकेशन डेस्कटॉप विंडोइंग मोड में खुला होता है, तो अन्य ऐप्लिकेशन भी डेस्कटॉप विंडो में खुलते हैं.

दूसरी इमेज. डेस्कटॉप विंडोविंग में जाने के लिए, ऐप्लिकेशन विंडो के हैंडल को दबाकर रखें और खींचें.

उपयोगकर्ता, डेस्कटॉप विंडो को छोटा करने की सुविधा को उस मेन्यू से भी चालू कर सकते हैं जो विंडो हैंडल के नीचे दिखता है. इसके लिए, उन्हें हैंडल पर टैप या क्लिक करना होगा. इसके अलावा, वे कीबोर्ड शॉर्टकट मेटा बटन (Windows, Command या Search) + Ctrl + Down का इस्तेमाल करके भी इस सुविधा को चालू कर सकते हैं.

उपयोगकर्ता, डेस्कटॉप विंडो को बंद करने के लिए, सभी चालू विंडो बंद करते हैं. इसके अलावा, वे डेस्कटॉप विंडो में सबसे ऊपर मौजूद विंडो हैंडल को पकड़कर, ऐप्लिकेशन को स्क्रीन पर सबसे ऊपर खींचकर छोड़ते हैं. Meta + H कीबोर्ड शॉर्टकट से भी डेस्कटॉप विंडोविंग मोड बंद हो जाता है और ऐप्लिकेशन फिर से फ़ुल स्क्रीन पर चलने लगते हैं.

डेस्कटॉप विंडो पर वापस जाने के लिए, हाल ही के ऐप्लिकेशन वाली स्क्रीन में मौजूद डेस्कटॉप स्पेस टाइल पर टैप करें या क्लिक करें.

रीसाइज़ करने की सुविधा और कंपैटबिलिटी मोड

डेस्कटॉप विंडोइंग में, लॉक किए गए ओरिएंटेशन वाले ऐप्लिकेशन का साइज़ आसानी से बदला जा सकता है. इसका मतलब है कि अगर कोई ऐक्टिविटी पोर्ट्रेट ओरिएंटेशन के लिए लॉक है, तो भी उपयोगकर्ता ऐप्लिकेशन को लैंडस्केप ओरिएंटेशन वाली विंडो के हिसाब से रीसाइज़ कर सकते हैं.

तीसरी इमेज. पोर्ट्रेट मोड में काम करने वाले ऐप्लिकेशन की विंडो का साइज़ बदलकर लैंडस्केप मोड में करना.

जिन ऐप्लिकेशन को रीसाइज़ नहीं किया जा सकता (यानी कि resizeableActivity = false), उनके यूज़र इंटरफ़ेस (यूआई) को स्केल किया जाता है. हालांकि, ऐसा करते समय आसपेक्ट रेशियो में कोई बदलाव नहीं किया जाता.

चौथी इमेज. विंडो का साइज़ बदलने पर, साइज़ न बदलने वाले ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) स्केल हो जाता है.

कैमरा ऐप्लिकेशन, ओरिएंटेशन लॉक कर देते हैं या उन्हें नॉनरीसाइज़ेबल के तौर पर सेट कर दिया जाता है. ऐसे ऐप्लिकेशन के कैमरा व्यूफ़ाइंडर के लिए खास सुविधा उपलब्ध होती है: विंडो का साइज़ पूरी तरह से बदला जा सकता है, लेकिन व्यूफ़ाइंडर का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) एक जैसा रहता है. ऐप्लिकेशन हमेशा पोर्ट्रेट या लैंडस्केप मोड में चलते हैं. इसलिए, ऐप्लिकेशन हार्डकोड करते हैं या अन्य तरह से अनुमान लगाते हैं. इससे, झलक या कैप्चर की गई इमेज के ओरिएंटेशन या आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) की गलत गणना होती है. इस वजह से, इमेज खिंची हुई, साइडवे या उल्टी दिखती हैं.

जब तक ऐप्लिकेशन, पूरी तरह से रिस्पॉन्सिव कैमरा व्यूफ़ाइंडर लागू करने के लिए तैयार नहीं हो जाते, तब तक खास तौर पर तैयार किए गए इस समाधान से, उपयोगकर्ता को बेहतर अनुभव मिलता है. साथ ही, इससे गलत अनुमानों की वजह से होने वाले असर को कम किया जा सकता है.

कैमरा ऐप्लिकेशन के लिए कंपैटिबिलिटी मोड के बारे में ज़्यादा जानने के लिए, डिवाइस कंपैटिबिलिटी मोड लेख पढ़ें.

पांचवीं इमेज. विंडो का साइज़ बदलने पर भी, कैमरा व्यूफ़ाइंडर का आसपेक्ट रेशियो (लंबाई-चौड़ाई का अनुपात) नहीं बदलता.

पसंद के मुताबिक बनाए जा सकने वाले हेडर इंसर्ट

डेस्कटॉप विंडोइंग मोड में चल रहे सभी ऐप्लिकेशन में हेडर बार होता है. यह इमर्सिव मोड में भी दिखता है. इस बार को अपनी पसंद के मुताबिक बनाया जा सकता है, ताकि आपके ऐप्लिकेशन का कॉन्टेंट न दिखे. साथ ही, हेडर स्पेस में सीधे तौर पर कस्टम यूज़र इंटरफ़ेस (यूआई) एलिमेंट बनाए जा सकें.

कस्टम हेडर लागू करने से पहले और बाद में Chrome.
छठी इमेज. कस्टम हेडर लागू करने से पहले और बाद में Chrome.

लागू करना

हेडर बार में कस्टम कॉन्टेंट बनाने के लिए, सबसे पहले हेडर बार के बैकग्राउंड को पारदर्शी बनाएं. इसके लिए, WindowInsetsController के साथ APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND फ़्लैग का इस्तेमाल करें.

window.insetsController?.setSystemBarsAppearance(
    WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND,
    WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND
)

हेडर बार के पारदर्शी होने के बाद, हेडर एरिया को अपने ऐप्लिकेशन के डिज़ाइन के हिसाब से स्टाइल किया जा सकता है. WindowInsets.isCaptionBarVisible का इस्तेमाल करके यह पता लगाएं कि बार मौजूद है या नहीं. इसके बाद, अपने लेआउट पर सही ऊंचाई या पैडिंग लागू करें.

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun CaptionBar() {
    if (WindowInsets.isCaptionBarVisible) {
        Row(
            modifier = Modifier
                .windowInsetsTopHeight(WindowInsets.captionBar)
                .fillMaxWidth()
                .background(if (isSystemInDarkTheme()) Color.White else Color.Black),
            horizontalArrangement = Arrangement.Center,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = "Caption Bar Title",
                style = MaterialTheme.typography.titleMedium,
                modifier = Modifier.padding(4.dp)
            )
        }
    }
}

  • setSystemBarsAppearance(appearance,mask): इससे सिस्टम बार की विज़ुअल स्टाइल कॉन्फ़िगर की जाती है. पहले पैरामीटर से, टारगेट किए गए प्रॉडक्ट के दिखने से जुड़े फ़्लैग तय होते हैं. वहीं, दूसरा पैरामीटर एक मास्क के तौर पर काम करता है. इससे यह कंट्रोल किया जाता है कि कौनसे फ़्लैग में बदलाव किया गया है.

  • windowInsetsTopHeight(): यह आपके कंपोज़ेबल की ऊंचाई को सिस्टम के हेडर बार से मैच करने के लिए अपने-आप सेट करता है. इससे आपके कस्टम बैकग्राउंड को पिक्सल वैल्यू को हार्डकोड किए बिना, कैप्शन एरिया को भरने में मदद मिलती है.

  • WindowInsets.captionBar: यह डेस्कटॉप विंडोविंग कंट्रोल (बंद करें, ज़्यादा से ज़्यादा करें वगैरह) के डाइमेंशन उपलब्ध कराता है. इससे डेस्कटॉप विंडोविंग में जाने या उससे बाहर निकलने पर, आपका यूज़र इंटरफ़ेस (यूआई) अपने-आप स्केल हो जाता है या छिप जाता है.

ज़्यादा जानकारी के लिए, विंडो इंसर्ट के बारे में जानकारी लेख पढ़ें. टाइटल के अलावा, कैप्शन बार में अन्य यूज़र इंटरफ़ेस (यूआई) एलिमेंट भी दिखाए जा सकते हैं. जैसे, टैब—जैसे कि Google Chrome में—खोज बार या प्रोफ़ाइल अवतार.

उपयोगकर्ता इंटरफ़ेस

Android 15, सिस्टम बटन के साथ यूज़र इंटरफ़ेस (यूआई) के ओवरलैप होने से बचने के लिए, WindowInsets#getBoundingRects() तरीका उपलब्ध कराता है. यह तरीका, Rect ऑब्जेक्ट की एक सूची दिखाता है. ये ऑब्जेक्ट, सिस्टम के एलिमेंट के लिए उपलब्ध जगहों को दिखाते हैं. कैप्शन बार में बचा हुआ स्पेस, सेफ़ ज़ोन होता है. इसमें कस्टम कॉन्टेंट को सुरक्षित तरीके से रखा जा सकता है.

APPEARANCE_LIGHT_CAPTION_BARS का इस्तेमाल करके, हल्के और गहरे रंग वाली थीम के लिए सिस्टम कैप्शन एलिमेंट की थीम टॉगल करें. Compose में WindowInsets.Companion.captionBar() या Views में WindowInsets.Type.captionBar() का इस्तेमाल करके, इनसेट ऐक्सेस करें.

ज़्यादा जानकारी के लिए, विंडो इंसर्ट के बारे में जानकारी लेख पढ़ें.

मल्टीटास्किंग और एक से ज़्यादा इंस्टेंस इस्तेमाल करने की सुविधा

डेस्कटॉप विंडोविंग की सुविधा का मुख्य मकसद मल्टीटास्किंग है. अपने ऐप्लिकेशन के एक से ज़्यादा इंस्टेंस इस्तेमाल करने की अनुमति देने से, लोगों की प्रॉडक्टिविटी बढ़ सकती है.

Android 15 से, PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI का इस्तेमाल किया जा सकता है. AndroidManifest.xml में इस प्रॉपर्टी को सेट करके, यह तय किया जाता है कि सिस्टम यूज़र इंटरफ़ेस (यूआई) को ऐप्लिकेशन के लिए विकल्प (जैसे, "नई विंडो" बटन) उपलब्ध कराने चाहिए, ताकि ऐप्लिकेशन को एक से ज़्यादा इंस्टेंस में लॉन्च किया जा सके.

<application>
    <property
        android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
        android:value="true" />
</application>

ध्यान दें: डेस्कटॉप पर विंडो बनाने और मल्टी-विंडो वाले अन्य एनवायरमेंट में, नए टास्क नई विंडो में खुलते हैं. इसलिए, जब भी आपका ऐप्लिकेशन एक साथ कई टास्क शुरू करता है, तो उपयोगकर्ता के अनुभव की दोबारा जांच करें.

ड्रैग करने के जेस्चर की मदद से, ऐप्लिकेशन इंस्टेंस मैनेज करना

मल्टी-विंडो मोड में, उपयोगकर्ता किसी ऐप्लिकेशन की विंडो से यूज़र इंटरफ़ेस (यूआई) एलिमेंट (जैसे, टैब या दस्तावेज़) को खींचकर बाहर ले जा सकते हैं. इससे ऐप्लिकेशन का नया इंस्टेंस शुरू हो जाता है. उपयोगकर्ता, एक ही ऐप्लिकेशन के अलग-अलग इंस्टेंस के बीच एलिमेंट भी ले जा सकते हैं.

सातवीं इमेज. डेस्कटॉप विंडो से किसी टैब को बाहर खींचकर, Chrome का नया इंस्टेंस शुरू करें.

खींचने और छोड़ने की सुविधा का इस्तेमाल करके डेटा ट्रांसफ़र करना

एक से ज़्यादा इंस्टेंस में खींचकर छोड़ने की सुविधा के लिए, किसी कंपोज़ेबल को ड्रैग सोर्स के तौर पर कॉन्फ़िगर करने के लिए, dragAndDropSource मॉडिफ़ायर का इस्तेमाल करें. इससे उपयोगकर्ताओं को आपके ऐप्लिकेशन के किसी दूसरे इंस्टेंस में कॉन्टेंट को खींचकर छोड़ने की सुविधा मिलती है. इसके अलावा, स्क्रीन के खाली हिस्से पर कॉन्टेंट को छोड़कर, नया इंस्टेंस बनाया जा सकता है. इसके लैम्डा में, DragAndDropTransferData को वापस लाएं. साथ ही, ट्रांसफ़र करने के लिए ClipData और मल्टी-इंस्टेंस के व्यवहार को कॉन्फ़िगर करने के लिए फ़्लैग पास करें.

Android 15 में, डेस्कटॉप स्टाइल विंडोविंग और मल्टी-इंस्टेंस इंटरैक्शन के लिए दो मुख्य फ़्लैग जोड़े गए हैं:

  • DRAG_FLAG_GLOBAL_SAME_APPLICATION: इससे पता चलता है कि ड्रैग करने की कार्रवाई, विंडो की सीमाओं को पार कर सकती है. ऐसा एक ही ऐप्लिकेशन के कई इंस्टेंस के लिए किया जा सकता है. इस फ़्लैग को सेट करके startDragAndDrop() को कॉल करने पर, सिर्फ़ एक ही ऐप्लिकेशन से जुड़े दिखने वाले विंडो, ड्रैग ऑपरेशन में हिस्सा ले सकते हैं और ड्रैग किया गया कॉन्टेंट पा सकते हैं.

Modifier.dragAndDropSource { _ ->
    DragAndDropTransferData(
        clipData = ClipData.newPlainText("label", "Your data"),
        flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION
    )
}

  • DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: इससे उपयोगकर्ता, स्क्रीन के खाली हिस्से पर ड्रैग किए गए कॉन्टेंट को छोड़कर, आपके ऐप्लिकेशन का नया इंस्टेंस शुरू कर सकते हैं. ऐसा तब किया जा सकता है, जब कोई दूसरी विंडो कॉन्टेंट को ड्रॉप करने की सुविधा नहीं देती है.

Modifier.dragAndDropSource { _ ->
    val intent = Intent.makeMainActivity(activity.componentName).apply {
        putExtra("EXTRA_ITEM_ID", itemId)
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or
                Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
                Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
    }

    val pendingIntent = PendingIntent.getActivity(
        activity, 0, intent, PendingIntent.FLAG_IMMUTABLE
    )

    val data = ClipData(
        "Item $itemId",
        arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT),
        ClipData.Item.Builder().setIntentSender(pendingIntent.intentSender).build()
    )

    DragAndDropTransferData(
        clipData = data,
        flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION or
                View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
    )
}

ट्रांसफ़र किया गया डेटा पाना

किसी दूसरे इंस्टेंस से डेटा स्वीकार करने के लिए, dragAndDropTarget मॉडिफ़ायर का इस्तेमाल करें. अगर डेटा किसी दूसरे इंस्टेंस या ऐप्लिकेशन से आ रहा है, तो आपको साफ़ तौर पर अनुमतियों का अनुरोध करना होगा.

Modifier.dragAndDropTarget(
    shouldStartDragAndDrop = { event ->
        event.toAndroidDragEvent().clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)
    },
    target = object : DragAndDropTarget {
        override fun onDrop(event: DragAndDropEvent): Boolean {
            requestDragAndDropPermissions(activity, event.toAndroidDragEvent())
            val clipData = event.toAndroidDragEvent().clipData
            val item = clipData?.getItemAt(0)?.text
            if (item != null) {
                // Process the dropped text item here
            }
            return item != null
        }
    }
)

मुख्य चरण:

  • फ़िल्टर: shouldStartDragAndDrop का इस्तेमाल करके देखें कि आने वाला डेटा (MIME टाइप) काम करता है या नहीं.
  • अनुमतियां: डेटा ऐक्सेस करने के लिए, requestDragAndDropPermissions(event) को कॉल करें.
  • कार्रवाई: onDrop कॉलबैक में डेटा निकालें.

अन्य ऑप्टिमाइज़ेशन

ऐप्लिकेशन लॉन्च करने की सुविधा को पसंद के मुताबिक बनाएं और ऐप्लिकेशन को डेस्कटॉप विंडोविंग से फ़ुल स्क्रीन पर ले जाएं.

डिफ़ॉल्ट साइज़ और पोज़िशन की जानकारी देना

यह ज़रूरी नहीं है कि साइज़ बदलने की सुविधा वाले सभी ऐप्लिकेशन को, उपयोगकर्ताओं को बेहतर अनुभव देने के लिए बड़ी विंडो की ज़रूरत हो. गतिविधि लॉन्च होने पर, डिफ़ॉल्ट साइज़ और पोज़िशन तय करने के लिए, ActivityOptions#setLaunchBounds() तरीके का इस्तेमाल किया जा सकता है.

डेस्कटॉप स्पेस से फ़ुल-स्क्रीन मोड में जाना

ऐप्लिकेशन, Activity#requestFullScreenMode() को कॉल करके फ़ुल-स्क्रीन मोड में जा सकते हैं. इस तरीके से, ऐप्लिकेशन को सीधे डेस्कटॉप विंडोविंग से फ़ुल स्क्रीन में दिखाया जाता है.