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, masaüstü pencereleme özelliği etkinleştirilmişken ekranın düzenini görebilirsiniz. Önemli noktalar:

  • Kullanıcılar, birden fazla uygulamayı aynı anda 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ı küçültme ve büyütme gibi kontrollerle süsler.
Alt kısmında görev çubuğu bulunan, yeniden boyutlandırılabilir pencerelerde çalışan birden fazla uygulamanın gösterildiği bir tablet ekranı.
Şekil 1. Tablette pencereli görüntüleme

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

Bir uygulama masaüstü pencereleme modunda açıkken diğer uygulamalar da masaüstü pencerelerinde açılır.

Şekil 2. Uygulama penceresi tutamacını basılı tutup sürükleyerek masaüstü pencere moduna girin.

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ü pencere oluşturma özelliğini de etkinleştirebilir.

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

Masaüstü pencere düzenine 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ü pencereleme özelliğinde, 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önde 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ü, aynı 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ığı varsayıldığında, uygulamalar önizleme ya da çekilen resim yönünün veya en boy oranının yanlış hesaplanmasına yol açan kodlar ya da başka varsayımlar kullanır. Bu da 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 üzere 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ü pencere 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 başlık çubuğu tarafından gizlenmediğini doğrulayın. Başlık çubuğu, sistem çubuklarının bir parçası olan görünümlerde WindowInsets.Companion.captionBar(); WindowInsets.Type.captionBar(); bir başlık çubuğu yerleştirme türüdür.

Yerleşimleri işleme hakkında daha fazla bilgiyi Uygulamanızda içeriği uçtan uca görüntüleme ve Compose'da pencere yerleşimlerini işleme başlıklı makalede bulabilirsiniz.

Başlık çubuğu da özelleştirilebilir. Android 15, uygulamaların başlık çubuğunun içine özel içerik çizmesine olanak tanımak için başlık çubuğunu şeffaf hale getiren görünüm türünü APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND tanıttı.

Uygulamalar, içeriklerinin üst kısmını altyazı çubuğuna benzeyecek şekilde (arka plan, özel içerik vb.) biçimlendirmekten sorumlu olur. Sistem altyazı öğeleri (kapatma ve büyütme düğmeleri) hariçtir. Bu öğeler, uygulama üzerinde şeffaf altyazı çubuğunda sistem tarafından çizilir.

Uygulamalar, durum çubuğu ve gezinme çubuğunun değiştirilmesine benzer şekilde, APPEARANCE_LIGHT_CAPTION_BARS kullanarak altyazı içindeki sistem öğelerinin görünümünü açık ve koyu temalar arasında değiştirebilir.

Android 15, uygulamaların altyazı çubuğu eklerini daha ayrıntılı bir şekilde incelemesini sağlayan WindowInsets#getBoundingRects() yöntemini de kullanıma sundu. Uygulamalar, sistemin sistem öğelerini çizdiği alanlar ile uygulamaların sistem öğeleriyle çakışmadan özel içerik yerleştirebileceği kullanılmayan alanlar arasında ayrım yapabilir.

API tarafından döndürülen Rect nesnelerin listesi, kaçınılması gereken sistem bölgelerini gösterir. Kalan alan (altyazı çubuğu iç kısımlarından dikdörtgenler çıkarılarak hesaplanır), uygulamanın sistem öğeleriyle çakışmadan ve giriş alabilme özelliğiyle çizim yapabileceği yerdir.

Özel üstbilgiler uygulanmadan önce ve uygulandıktan sonra Chrome.
Şekil 6. Özel üstbilgiler uygulanmadan önce ve uygulandıktan sonra Chrome.

Özel bir başlık için sistem hareketi hariç tutma dikdörtgenleri ayarlamak üzere görünümünüzde veya Composable'ınızda aşağıdakileri uygulayın:

// In a custom View's onLayout or a similar lifecycle method
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
    super.onLayout(changed, left, top, right, bottom)
    if (changed) {
        // Calculate the height of your custom header
        val customHeaderHeight = 100 // Replace with your actual header height in pixels

        // Create a Rect covering your custom header area
        val exclusionRect = Rect(0, 0, width, customHeaderHeight)

        // Set the exclusion rects for the system
        systemGestureExclusionRects = listOf(exclusionRect)
    }
}

Çoklu görev ve çoklu örnek desteği

Çoklu görev, masaüstü pencere sisteminin temelini oluşturur. Uygulamanızın birden fazla örneğine izin vermek, kullanıcıların üretkenliğini önemli ölçüde artırabilir.

Android 15, uygulamaların birden fazla örnek olarak başlatılabilmesi için sistem kullanıcı arayüzünün gösterilmesi gerektiğini belirtmek üzere ayarlayabileceği PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI özelliğini sunuyor.

PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, <activity> etiketi içindeki uygulamanızın AndroidManifest.xml bölümünde beyan edebilirsiniz:

<activity
    android:name=".MyActivity"
    android:exported="true"
    android:resizeableActivity="true">
    <meta-data
        android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
        android:value="true" />
</activity>

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

Çok pencereli modda kullanıcılar, bir görünüm öğesini uygulamanın penceresinden dışarı sürükleyerek yeni bir uygulama örneği başlatabilir. Kullanıcılar, aynı uygulamanın örnekleri arasında da öğe taşıyabilir.

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

Android 15, sürükleme davranışını özelleştirmek için iki işaret sunar:

  • DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: Görünür bir pencere bırakma işlemini yapmıyorsa işlenmemiş bir sürükleme işleminin başlatılması için sisteme devredilmesi gerektiğini gösterir. Bu işaret kullanılırken arayan, başlatılacak bir etkinliğe yönelik değişmez bir IntentSender içeren bir ClipData ile ClipData.Item sağlamalıdır (ClipData.Item.Builder#setIntentSender() bölümüne bakın). Sistem, mevcut ekran boyutu veya pencere modu gibi faktörlere bağlı olarak amaçlı işlemi başlatabilir veya başlatmayabilir. Sistem, amaçlı işlemi başlatmazsa amaçlı işlem normal sürükleme akışıyla iptal edilir.

  • DRAG_FLAG_GLOBAL_SAME_APPLICATION: Bir sürükleme işleminin pencere sınırlarını aşabileceğini (aynı uygulamanın birden fazla örneği için) gösterir.

    Bu işaret ayarlanmışken [startDragAndDrop()][20] ç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.

Aşağıdaki örnekte bu işaretlerin startDragAndDrop() ile nasıl kullanılacağı gösterilmektedir:

// Assuming 'view' is the View that initiates the drag
view.setOnLongClickListener {
    // Create an IntentSender for the activity you want to launch
    val launchIntent = Intent(view.context, NewInstanceActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(
        view.context,
        0,
        launchIntent,
        PendingIntent.FLAG_IMMUTABLE // Ensure the PendingIntent is immutable
    )

    // Build the ClipData.Item with the IntentSender
    val item = ClipData.Item.Builder()
        .setIntentSender(pendingIntent.intentSender)
        .build()

    // Create ClipData with a simple description and the item
    val dragData = ClipData(
        ClipDescription("New Instance Drag", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN)),
        item
    )

    // Combine the drag flags
    val dragFlags = View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG or
                    View.DRAG_FLAG_GLOBAL_SAME_APPLICATION

    // Start the drag operation
    view.startDragAndDrop(
        dragData,                     // The ClipData to drag
        View.DragShadowBuilder(view), // A visual representation of the dragged item
        null,                         // Local state object (not used here)
        dragFlags                     // The drag flags
    )
    true // Indicate that the long click was consumed
}
Şekil 8. Chrome uygulamasının iki örneği arasında sekme taşıma.

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 boyut ve konum belirtmek için ActivityOptions#setLaunchBounds() yöntemini kullanabilirsiniz.

Aşağıda, bir etkinlik için yayınlanma sınırlarının nasıl ayarlanacağına dair bir örnek verilmiştir:

val options = ActivityOptions.makeBasic()

// Define the desired launch bounds (left, top, right, bottom in pixels)
val launchBounds = Rect(100, 100, 700, 600) // Example: 600x500 window at (100,100)

// Apply the launch bounds to the ActivityOptions
options.setLaunchBounds(launchBounds)

// Start the activity with the specified options
val intent = Intent(this, MyActivity::class.java)
startActivity(intent, options.toBundle())

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ü penceresinden tam ekran olarak gösterir.

Bir etkinlikten tam ekran modu isteğinde bulunmak için aşağıdaki kodu kullanın:

// In an Activity
fun enterFullScreen() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 15 (U)
        requestFullScreenMode()
    }
}