Masaüstü pencerelerini destekleme

Pencereli görüntüleme, kullanıcıların çok yönlü ve masaüstüne benzer bir deneyim için yeniden boyutlandırılabilir uygulama pencerelerinde aynı anda birden fazla uygulama çalıştırmasına olanak tanır.

Şekil 1'de, pencereli görüntüleme etkin durumdayken ekranın düzenini görebilirsiniz. Önemli noktalar:

  • Kullanıcılar aynı anda birden fazla uygulamayı yan yana çalıştırabilir.
  • Görev çubuğu, çalışan uygulamaları gösteren ekranın alt kısmında sabit bir konumdadır. Kullanıcılar, uygulamaları hızlı erişim için sabitleyebilir.
  • Yeni özelleştirilebilir başlık çubuğu, her pencerenin üst kısmını simge durumuna küçültme ve ekranı kaplama gibi kontrollerle süsler.
Şekil 1. Tablette pencereli görüntüleme

Android tabletlerde uygulamalar varsayılan olarak tam ekranda açılır. Bir uygulamayı pencereli görüntülemede başlatmak için ekranın üst kısmındaki pencere tutma yerine basılı tutun ve tutma yerini Şekil 2'de gösterildiği gibi kullanıcı arayüzünde sürükleyin.

Bir uygulama pencereli görüntülemede açıkken diğer uygulamalar da masaüstü pencerelerinde açılır.

Şekil 2. Pencereli görüntülemeye girmek için uygulama penceresi tutma yerini basılı tutun ve sürükleyin.

Kullanıcılar, pencere tutamacına dokunduklarında veya tutamacı tıkladıklarında pencere tutamacının altında gösterilen menüden ya da Meta tuşu (Windows, Command veya Search) + Ctrl + Aşağı klavye kısayolunu kullanarak masaüstü pencereli görüntüleme özelliğini de etkinleştirebilir.

Kullanıcılar, etkin pencerelerin tümünü kapatarak veya masaüstü penceresinin üst kısmındaki pencere tutamacını tutup uygulamayı ekranın üst kısmına sürükleyerek pencereli görüntüleme modundan çıkabilir. Meta + H klavye kısayolu da masaüstü pencere modundan çıkar ve uygulamaları tekrar tam ekran olarak çalıştırır.

Pencereli görüntülemeye dönmek için Son Kullanılanlar ekranında masaüstü alanı kutucuğuna dokunun veya bu kutucuğu tıklayın.

Yeniden boyutlandırma ve uyumluluk modu

Masaüstü pencereli görüntüleme modunda, yönü kilitlenmiş uygulamaların boyutu serbestçe ayarlanabilir. Bu nedenle, bir etkinlik dikey yöne kilitlenmiş olsa bile kullanıcılar uygulamayı yatay yönlü bir pencereye yeniden boyutlandırabilir.

Şekil 3. Portre moduyla sınırlı bir uygulamanın penceresini yatay moda yeniden boyutlandırma.

Yeniden boyutlandırılamaz olarak beyan edilen uygulamaların (yani resizeableActivity = false) kullanıcı arayüzü, en-boy oranı korunarak ölçeklendirilir.

Şekil 4. Yeniden boyutlandırılamayan bir uygulamanın kullanıcı arayüzü, pencere yeniden boyutlandırıldıkça ölçeklenir.

Yönü kilitleyen veya yeniden boyutlandırılamaz olarak bildirilen kamera uygulamalarının kamera vizörleri için özel bir işlem uygulanır: Pencere tamamen yeniden boyutlandırılabilir ancak vizör aynı en-boy oranını korur. Uygulamaların her zaman dikey veya yatay modda çalıştığını varsayarak, uygulamalar önizleme ya da çekilen resim yönünün veya en-boy oranının yanlış hesaplanmasına yol açan kodlar oluşturur ya da başka varsayımlarda bulunur. Bu durum, resimlerin gergin, yan veya baş aşağı görünmesine neden olur.

Uygulamalar tam olarak duyarlı kamera vizörlerini uygulamaya hazır olana kadar, özel işlem, yanlış varsayımların neden olabileceği etkileri azaltan daha temel bir kullanıcı deneyimi sunar.

Kamera uygulamaları için uyumluluk modu hakkında daha fazla bilgi edinmek istiyorsanız Cihaz uyumluluk modu başlıklı makaleyi inceleyin.

Şekil 5. Pencere yeniden boyutlandırıldığında kamera vizörü en boy oranını korur.

Özelleştirilebilir başlık iç kısımları

Masaüstü pencereli görüntüleme modunda çalışan tüm uygulamaların tam ekran modunda bile bir başlık çubuğu vardır. Uygulamanızın içeriğinin gizlenmesini önlemek ve özel kullanıcı arayüzü öğelerini doğrudan başlık alanına çizmek için bu çubuğu özelleştirebilirsiniz.

Özel başlıklar uygulanmadan önce ve uygulandıktan sonra Chrome
Şekil 6. Özel başlıklar uygulanmadan önce ve uygulandıktan sonra Chrome

Uygulama

Başlık çubuğunda özel içerik çizmek için ilk adım, başlık çubuğu arka planını şeffaf hale getirmektir. Bunu, WindowInsetsController ile birlikte APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND işaretini kullanarak yapabilirsiniz.

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

Başlık çubuğu şeffaf hale geldiğinde başlık alanını uygulamanızın tasarımına uygun şekilde biçimlendirebilirsiniz. Çubuğun mevcut olup olmadığını algılamak ve düzeninize uygun yüksekliği veya dolguyu uygulamak için WindowInsets.isCaptionBarVisible öğesini kullanın.

@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): Sistem çubuklarının görsel stilini yapılandırır. İlk parametre hedef görünüm işaretlerini tanımlarken ikinci parametre, hangi işaretlerin değiştirileceğini kontrol etmek için maske görevi görür.

  • windowInsetsTopHeight(): Composable'ınızın yüksekliğini sistemin başlık çubuğuyla eşleşecek şekilde otomatik olarak ayarlar. Böylece özel arka planınız, piksel değerlerini sabit kodlamadan altyazı alanını doldurur.

  • WindowInsets.captionBar: Masaüstü pencereli görüntüleme kontrollerinin (Kapat, Ekranı kapla vb.) boyutlarını sağlar. Böylece, masaüstü pencereli görüntülemeye girildiğinde veya çıkıldığında kullanıcı arayüzünüzün otomatik olarak ölçeklenmesine ya da gizlenmesine olanak tanır.

Daha fazla bilgi için Pencere iç kenarları hakkında başlıklı makaleyi inceleyin. Başlığa ek olarak, altyazı çubuğunda diğer kullanıcı arayüzü öğelerini (ör. Google Chrome'daki gibi sekmeler, arama çubukları veya profil avatarları) de gösterebilirsiniz.

Kullanıcı arayüzü

Android 15, kullanıcı arayüzünüzün sistem düğmeleriyle çakışmasını önlemek için WindowInsets#getBoundingRects() yöntemini sunar. Bu yöntem, sistem öğelerinin kapladığı alanları temsil eden Rect nesnelerinin listesini döndürür. Altyazı çubuğunda kalan alan, özel içerikleri güvenle yerleştirebileceğiniz bir güvenli bölgedir.

APPEARANCE_LIGHT_CAPTION_BARS simgesini kullanarak açık ve koyu temalarda sistem altyazı öğelerinin görünümünü değiştirin. Oluşturma'da WindowInsets.Companion.captionBar() veya Görünümler'de WindowInsets.Type.captionBar() simgesini kullanarak ekleri görüntüleyin.

Daha fazla bilgi için Pencere iç kenarları hakkında başlıklı makaleyi inceleyin.

Çoklu görev ve aynı anda çalışan birden çok kopya desteği

Çoklu görev, pencereli görüntülemenin temelinde yer alır. Uygulamanızın birden fazla örneğine izin vermek, kullanıcıların üretkenliğini önemli ölçüde artırabilir.

Android 15'ten itibaren PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI kullanabilirsiniz. Bu özelliği AndroidManifest.xml içinde ayarlayarak sistem kullanıcı arayüzünün, uygulamanın birden fazla örnekte başlatılması için seçenekler (ör. "Yeni Pencere" düğmesi) sunması gerektiğini belirtirsiniz.

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

Not: Masaüstü pencereli görüntüleme ve diğer çoklu pencere ortamlarında yeni görevler yeni bir pencerede açılır. Bu nedenle, uygulamanız birden fazla görev başlattığında kullanıcı yolculuğunu tekrar kontrol edin.

Sürükleme hareketleriyle uygulama örneklerini yönetme

Çok pencereli modda kullanıcılar, bir kullanıcı arayüzü öğesini (ör. sekme veya doküman) uygulamanın penceresinden dışarı sürükleyerek yeni bir uygulama örneği başlatabilir. Kullanıcılar, aynı uygulamanın farklı örnekleri arasında da öğe taşıyabilir.

Şekil 7. Bir sekmeyi masaüstü penceresinden dışarı sürükleyerek yeni bir Chrome örneği başlatın.

Sürükleyip bırakarak veri aktarma

Bir composable'ı aynı anda çalışan birden çok kopya sürükle ve bırak işlemi için sürükleme kaynağı olarak yapılandırmak üzere (kullanıcıların içeriği uygulamanızın başka bir örneğine sürüklemesine veya içeriği ekranın boş bir alanına bırakarak yeni bir örnek oluşturmasına olanak tanımak için) dragAndDropSource değiştiricisini kullanın. Lambda'sında, aktarılacak verileri içeren ClipData ve aynı anda çalışan birden çok kopya davranışını yapılandırmak için kullanılan işaretleri ileterek DragAndDropTransferData değerini döndürün.

Android 15, masaüstü tarzı pencereleme ve aynı anda çalışan birden çok kopya etkileşimleri için iki önemli işaret sunar:

  • DRAG_FLAG_GLOBAL_SAME_APPLICATION: Bir sürükleme işleminin pencere sınırlarını (aynı uygulamanın birden fazla örneği için) aşabileceğini gösterir. Bu işaret ayarlanmışken startDragAndDrop() çağrıldığında, yalnızca aynı uygulamaya ait görünür pencereler sürükleme işlemine katılabilir ve sürüklenen içeriği alabilir.

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

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,
    )
}

Aktarılan verileri alma

Başka bir örnekten gelen verileri kabul etmek için dragAndDropTarget değiştiricisini kullanın. Veriler farklı bir örnekten veya uygulamadan geliyorsa izinleri açıkça istemeniz gerekir.

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
        }
    }
)

Önemli adımlar:

  • Filtre: Gelen verilerin (MIME türü) desteklenip desteklenmediğini kontrol etmek için shouldStartDragAndDrop kullanın.
  • İzinler: Verilere erişmek için requestDragAndDropPermissions(event) işlevini çağırın.
  • İşleyici: onDrop geri çağırma işlevindeki verileri ayıklayın.

Ek optimizasyonlar

Uygulama başlatma işlemlerini özelleştirin ve uygulamaları pencereli görüntülemeden tam ekrana geçirin.

Varsayılan boyutu ve konumu belirtme

Yeniden boyutlandırılabilir olsa bile tüm uygulamaların kullanıcı değeri sunmak için büyük bir pencereye ihtiyacı yoktur. Bir etkinlik başlatıldığında varsayılan boyutu ve konumu belirtmek için ActivityOptions#setLaunchBounds() yöntemini kullanabilirsiniz.

Masaüstü alanından tam ekrana geçme

Uygulamalar, Activity#requestFullScreenMode() işlevini çağırarak tam ekran olabilir. Bu yöntem, uygulamayı doğrudan masaüstü pencereli görüntüleme modunda tam ekran olarak gösterir.