Etkinlik yerleştirme

Etkinlik yerleştirme, bir uygulamanın görev penceresini iki etkinliğe veya aynı etkinliğin iki örneği arasında bölerek büyük ekranlı cihazlardaki uygulamaları optimize eder.

Şekil 1. Etkinliklerin yan yana gösterildiği ayarlar uygulaması.

Uygulamanız birden fazla etkinlik içeriyorsa etkinliği yerleştirme; tabletlerde, katlanabilir cihazlarda ve ChromeOS cihazlarda gelişmiş bir kullanıcı deneyimi sunmanıza olanak tanır.

Etkinlik yerleştirme kodu yeniden düzenlemeye gerek yoktur. Bir XML yapılandırma dosyası oluşturarak veya Jetpack WindowManager API çağrıları yaparak uygulamanızın etkinliklerini (yan yana veya yığın halinde) nasıl görüntüleyeceğini belirlersiniz.

Küçük ekranlara yönelik destek otomatik olarak sağlanır. Uygulamanız küçük ekranlı bir cihazdaysa etkinlikler üst üste yığılır. Büyük ekranlarda etkinlikler yan yana gösterilir. Sistem, oluşturduğunuz yapılandırmaya göre sunumu belirler. Kollara ayırma mantığına gerek yoktur.

Etkinlik yerleştirme özelliği, cihazın yönüyle ilgili değişikliklere uyum sağlar ve katlanabilir cihazlarda sorunsuz şekilde çalışır. Cihaz katlanabilir cihazlarda üst üste bindirilip ayırma işlemleri yapılır.

Etkinlik yerleştirme özelliği, Android 12L (API düzeyi 32) ve sonraki sürümleri çalıştıran çoğu büyük ekranlı cihazda desteklenir.

Görev penceresini böl

Etkinlik yerleştirme, uygulama görev penceresini iki kapsayıcıya böler: birincil ve ikincil. Kapsayıcılar, ana etkinlikten veya halihazırda container'larda bulunan diğer etkinliklerden başlatılan etkinlikleri barındırır.

Etkinlikler, başlatıldıklarında ikincil kapsayıcıda yığılır ve ikincil kapsayıcı küçük ekranlarda birincil kapsayıcının üzerine yığılır. Böylece etkinlik yığma ve geri gezinme, halihazırda uygulamanızda yerleşik olarak bulunan etkinliklerin sıralamasıyla tutarlıdır.

Etkinlik yerleştirme, etkinlikleri çeşitli şekillerde görüntülemenizi sağlar. Uygulamanız, iki etkinliği eşzamanlı olarak başlatarak görev penceresini bölebilir:

Şekil 2. Yan yana duran iki etkinlik.

Veya tüm görev penceresini kaplayan bir etkinlik, yanında yeni bir etkinlik de başlatarak bir bölme oluşturabilir:

Şekil 3. A etkinliği, yan tarafta B aktivitesini başlatır.

Zaten bölünmüş olan ve bir görev penceresini paylaşan etkinlikler, diğer etkinlikleri aşağıdaki şekillerde başlatabilir:

  • Başka bir etkinliğin yanında:

    Şekil 4. A etkinliği, C aktivitesini B etkinliğinin yanında başlatır.
  • Yana doğru ve bölmeyi yana doğru kaydırarak önceki birincil etkinliği gizleyin:

    Şekil 5. B aktivitesi, C aktivitesini yana doğru başlatır ve bölmeyi yana doğru kaydırır.
  • En üstte, yani aynı etkinlik yığınında bir etkinlik başlatın:

    Şekil 6. B Etkinliği, fazladan amaç işaretleri olmadan C etkinliğini başlatır.
  • Aynı görevde bir etkinliği tam pencerede başlatma:

    Şekil 7. A etkinliği veya B etkinliği, görev penceresini dolduran C etkinliğini başlatır.

Geri gezinme

Etkinlikler arasındaki bağımlılıklara veya kullanıcıların geri etkinliğini tetikleme şekline bağlı olarak farklı uygulama türleri, bölünmüş görev penceresi durumunda farklı geri gezinme kurallarına sahip olabilir. Örneğin:

  • Birlikte gitme: Etkinlikler birbiriyle ilişkiliyse ve bir tanesi diğeri olmadan gösterilmesi gerekiyorsa, geri gezinme her ikisini de bitirecek şekilde yapılandırılabilir.
  • Tek başına devam etmek: Etkinlikler tamamen bağımsızsa bir etkinlikteki geri gezinme, görev penceresindeki başka bir etkinliğin durumunu etkilemez.

Geri etkinliği, düğmeyle gezinme kullanılırken odaklanılan son etkinliğe gönderilir. Harekete dayalı gezinme ile geri etkinliği, hareketin gerçekleştiği etkinliğe gönderilir.

Çok bölmeli düzen

Jetpack WindowManager Android 12L (API düzeyi 32) veya sonraki sürümlere sahip büyük ekranlı cihazlarda ve daha eski platform sürümlerine sahip bazı cihazlarda çok bölmeli etkinlik yerleştirebilmenizi sağlar. SlidingPaneLayout gibi parçalar veya görünüme dayalı düzenler yerine birden çok etkinliğe dayalı mevcut uygulamalar, kaynak kodu yeniden düzenlemeye gerek kalmadan iyileştirilmiş bir büyük ekran kullanıcı deneyimi sunabilir.

Liste-ayrıntısı bölme yöntemi, yaygın bir örnektir. Yüksek kaliteli bir sunum sağlamak için sistem, liste etkinliğini başlatır, ardından uygulama da hemen ayrıntı etkinliğini başlatır. Geçiş sistemi her iki etkinlik de çizilinceye kadar bekler, daha sonra bunları birlikte gösterir. Kullanıcı için iki etkinlik tek bir etkinlik olarak başlatılır.

Şekil 8. Çok bölmeli bir düzende, aynı anda başlatılan iki etkinlik.

Özellikleri ayırın

Görev penceresinin bölünmüş kapsayıcılar arasında nasıl orantılandırılacağını ve kapsayıcıların birbirlerine göre nasıl yerleştirileceğini belirtebilirsiniz.

XML yapılandırma dosyasında tanımlanan kurallar için aşağıdaki özellikleri ayarlayın:

  • splitRatio: Kapsayıcı oranlarını ayarlar. Değer, açık aralıktaki (0,0, 1,0) bir kayan nokta sayıdır.
  • splitLayoutDirection: Bölünmüş kapsayıcıların birbirine göre nasıl düzenleneceğini belirtir. Olası değerlere örnekler:
    • ltr: Soldan sağa
    • rtl: Sağdan sola
    • locale: ltr veya rtl, yerel ayardan belirlenir

Örnekler için aşağıdaki XML yapılandırması bölümüne bakın.

WindowManager API'leri kullanılarak oluşturulan kurallar için SplitAttributes.Builder ile bir SplitAttributes nesnesi oluşturun ve aşağıdaki oluşturucu yöntemlerini çağırın:

Örnekler için aşağıdaki WindowManager API’ye bakın.

Şekil 9. Soldan sağa yerleştirilmiş, ancak farklı bölme oranlarına sahip iki etkinlik bölümü var.

Yer tutucular

Yer tutucu etkinlikler, etkinlik bölümünün bir alanını kaplayan boş ikincil etkinliklerdir. Bunların yerine, içerik barındıran başka bir etkinlikle değiştirilmelidir. Örneğin, bir yer tutucu etkinliği, listeden bir öğe seçilene kadar liste ayrıntısı düzeninde bir etkinlik bölümünün ikincil tarafını kaplayabilir. Bu noktada, seçilen liste öğesine ilişkin ayrıntı bilgilerini içeren bir etkinlik yer tutucunun yerini alır.

Varsayılan olarak, sistem yer tutucuları yalnızca bir etkinlik bölümü için yeterli alan olduğunda görüntüler. Ekran boyutu, bölünme gösterilemeyecek kadar küçük bir genişliğe veya yüksekliğe dönüştüğünde yer tutucular otomatik olarak tamamlanır. Alan yeterli olduğunda, sistem yer tutucuyu yeniden başlatılmış durumu ile yeniden başlatır.

Şekil 10. Katlanabilir cihaz katlanabilir ve açılabilir. Yer tutucu etkinliği tamamlanır ve görüntü boyutu değiştikçe yeniden oluşturulur.

Ancak SplitPlaceholderRule veya setSticky() SplitPlaceholder.Builder yönteminin stickyPlaceholder özelliği varsayılan davranışı geçersiz kılabilir. Özellik veya yöntem true değerini belirttiğinde, ekran iki bölmeli ekrandan tek bölmeli ekrana küçültüldüğünde sistem yer tutucuyu görev penceresinde en üstteki etkinlik olarak görüntüler (örnek için Bölünmüş yapılandırma bölümüne bakın).

Şekil 11. Katlanabilir cihaz katlanabilir ve açılabilir. Yer tutucu etkinliği sabit.

Pencere boyutu değişiklikleri

Cihaz yapılandırmasında yapılan değişiklikler, görev penceresi genişliğini çok bölmeli bir düzen için yeterince büyük olmayacak şekilde azalttığında (örneğin, büyük ekranlı bir katlanabilir cihaz tablet boyutundan telefon boyutuna katlandığında veya uygulama penceresi çoklu pencere modunda yeniden boyutlandırıldığında), görev penceresinin ikincil bölmesindeki yer tutucu olmayan etkinlikler, birincil bölmedeki etkinliklerin üzerine yığılır.

Yer tutucu etkinlikleri yalnızca, bir bölüm için yeterli görüntü genişliği olduğunda gösterilir. Daha küçük ekranlarda yer tutucu otomatik olarak kapatılır. Görüntüleme alanı tekrar yeterince geniş hale geldiğinde yer tutucu yeniden oluşturulur. (Yukarıdaki Yer tutucular konusuna bakın.)

WindowManager, birincil bölmedeki etkinliklerin üzerinde bulunan ikincil bölmede etkinlikleri z ile sıraladığından etkinlik yığınları mümkündür.

İkincil bölmede birden fazla etkinlik

B Etkinliği, fazladan amaç işaretleri olmadan C etkinliğini başlatır:

A, B ve C etkinliklerini içeren etkinlik bölmesi ve C, B'nin üzerine yığılır.

ve bu da aynı görevdeki faaliyetlerin aşağıdaki z düzenine yol açar:

B'nin üzerine yığılmış C etkinliğini içeren ikincil etkinlik yığını.
          İkincil yığın, A etkinliğini içeren geçici etkinlik yığınının üzerine yığılır.

Bu nedenle, daha küçük bir görev penceresinde uygulama, yığının en üstünde C ile tek bir etkinliğe daralır:

Yalnızca C etkinliğini gösteren küçük pencere.

Küçük pencerede tekrar gezindiğinizde, birbirlerinin üzerine yığılmış etkinlikler arasında gezinirsiniz.

Görev penceresi yapılandırması birden fazla bölmeye uyum sağlayabilen daha büyük bir boyuta geri yüklenirse etkinlikler tekrar yan yana görüntülenir.

Yığın bölmeler

B aktivitesi, C aktivitesini yana doğru başlatır ve bölmeyi yana kaydırır:

A ve B etkinliklerini, ardından B ve C etkinliklerini gösteren görev penceresi.

Sonuç, aynı görevdeki etkinliklerin aşağıdaki z sırası olur:

Tek bir yığında A, B ve C etkinlikleri. Etkinlikler yukarıdan aşağıya şu sırayla yığılır: C, B, A.

Daha küçük bir görev penceresinde, uygulama en üstte C ile tek bir etkinliğe daralır:

Yalnızca C etkinliğini gösteren küçük pencere.

Sabit dikey yön

android:screenOrientation manifest ayarı, uygulamaların etkinlikleri dikey veya yatay yönle sınırlamasına olanak tanır. Cihaz üreticileri (OEM'ler), tabletler ve katlanabilir cihazlar gibi büyük ekranlı cihazlarda kullanıcı deneyimini iyileştirmek için ekran yönü isteklerini yok sayabilir ve yatay ekranlarda dikey yönde veya dikey ekranlarda yatay yönde uygulamayı yatay yönde çekebilirler.

Şekil 12. Sinemaskoplu etkinlikler: Yatay cihazda sabit dikey (sol), dikey cihazda sabit yatay (sağ).

Benzer şekilde, etkinlik yerleştirme özelliği etkinleştirildiğinde OEM'ler cihazları yatay yönde (genişlik ≥ 600 dp) sinemaskop sabit dikey aktivitelere göre özelleştirebilir. Sabit dikey bir etkinlik ikinci bir etkinliği başlattığında, cihaz iki etkinliği iki bölmeli bir ekranda yan yana görüntüleyebilir.

Şekil 13. Sabit dikey etkinlik A, B etkinliğini yanda başlatır.

Cihazlara, uygulamanızın etkinlik yerleştirmeyi desteklediğini bildirmek için android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED özelliğini her zaman uygulama manifest dosyanıza ekleyin (aşağıdaki Bölünmüş yapılandırma bölümüne bakın). OEM tarafından özelleştirilmiş cihazlar daha sonra sinemaskop sabit dikey dikey etkinliklerinin yapılıp yapılmayacağını belirleyebilir.

Bölünmüş yapılandırma

Bölme kuralları, etkinlik bölümlerini yapılandırır. Bölme kurallarını XML yapılandırma dosyasında veya Jetpack WindowManager API çağrıları yaparak tanımlarsınız.

Her iki durumda da uygulamanız WindowManager kitaplığına erişmeli ve sisteme uygulamanın etkinlik yerleştirme işlemini uyguladığını bildirmelidir.

Aşağıdakileri yapın:

  1. Uygulamanızın modül düzeyindeki build.gradle dosyasına en son WindowManager kitaplığı bağımlılığını ekleyin. Örneğin:

    implementation 'androidx.window:window:1.1.0-beta02'

    WindowManager kitaplığı, etkinlik yerleştirme için gereken tüm bileşenleri sağlar.

  2. Sisteme, uygulamanızda etkinlik yerleştirmeyi uyguladığını bildirin.

    android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED özelliğini uygulama manifest dosyasının <application> öğesine ekleyip değeri true olarak ayarlayın. Örneğin:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        <application>
            <property
                android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
                android:value="true" />
        </application>
    </manifest>
    

    WindowManager 1.1.0-alpha06 ve sonraki sürümlerde, özellik manifeste eklenip true değerine ayarlanmadığı sürece etkinlik yerleştirme grupları devre dışı bırakılır.

    Cihaz üreticileri de bu ayarı, etkinlik yerleştirmeyi destekleyen uygulamalarda özel özellikleri etkinleştirmek için kullanır. Örneğin, cihazlar ikinci bir etkinlik başladığında iki bölmeli düzene geçiş etkinliğini yönlendirmek için yatay ekranlarda yalnızca dikey yöndeki etkinliğe sinemaskop ekleyebilir (Sabit dikey yön bölümüne bakın).

XML yapılandırması

Etkinlik yerleştirmenin XML tabanlı bir uygulamasını oluşturmak için aşağıdaki adımları tamamlayın:

  1. Aşağıdaki işlemleri yapan bir XML kaynak dosyası oluşturun:

    • Ortak etkinlikleri tanımlar
    • Bölme seçeneklerini yapılandırır
    • İçerik mevcut olmadığında bölmenin ikincil kapsayıcısı için bir yer tutucu oluşturur
    • Asla bir bölmenin parçası olmaması gereken etkinlikleri belirtir

    Örneğin:

    <!-- main_split_config.xml -->
    
    <resources
        xmlns:window="http://schemas.android.com/apk/res-auto">
    
        <!-- Define a split for the named activities. -->
        <SplitPairRule
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:finishPrimaryWithSecondary="never"
            window:finishSecondaryWithPrimary="always"
            window:clearTop="false">
            <SplitPairFilter
                window:primaryActivityName=".ListActivity"
                window:secondaryActivityName=".DetailActivity"/>
        </SplitPairRule>
    
        <!-- Specify a placeholder for the secondary container when content is
             not available. -->
        <SplitPlaceholderRule
            window:placeholderActivityName=".PlaceholderActivity"
            window:splitRatio="0.33"
            window:splitLayoutDirection="locale"
            window:splitMinWidthDp="840"
            window:splitMaxAspectRatioInPortrait="alwaysAllow"
            window:stickyPlaceholder="false">
            <ActivityFilter
                window:activityName=".ListActivity"/>
        </SplitPlaceholderRule>
    
        <!-- Define activities that should never be part of a split. Note: Takes
             precedence over other split rules for the activity named in the
             rule. -->
        <ActivityRule
            window:alwaysExpand="true">
            <ActivityFilter
                window:activityName=".ExpandedActivity"/>
        </ActivityRule>
    
    </resources>
    
  2. Başlatıcı oluşturun.

    WindowManager RuleController bileşeni, XML yapılandırma dosyasını ayrıştırır ve kuralları sisteme kullanılabilir hale getirir. Jetpack Startup kitaplığı Initializer, XML dosyasını uygulama başlatılırken RuleController tarafından kullanılabilir hale getirir. Böylece, herhangi bir etkinlik başladığında kuralların geçerli olması sağlanır.

    Başlatıcı oluşturmak için aşağıdakileri yapın:

    1. Modül düzeyindeki build.gradle dosyanıza en son Jetpack Startup kitaplığı bağımlılığını ekleyin. Örneğin:

      implementation 'androidx.startup:startup-runtime:1.1.1'

    2. Initializer arayüzünü uygulayan bir sınıf oluşturun.

      Başlatıcı, XML yapılandırma dosyasının (main_split_config.xml) kimliğini RuleController.parseRules() yöntemine ileterek bölme kurallarını RuleController tarafından kullanılabilmesini sağlar.

      Kotlin

      class SplitInitializer : Initializer<RuleController> {
      
       override fun create(context: Context): RuleController {
           return RuleController.getInstance(context).apply {
               setRules(RuleController.parseRules(context, R.xml.main_split_config))
           }
       }
      
       override fun dependencies(): List<Class<out Initializer<*>>> {
           return emptyList()
       }
      }
      

      Java

      public class SplitInitializer implements Initializer<RuleController> {
      
        @NonNull
        @Override
        public RuleController create(@NonNull Context context) {
            RuleController ruleController = RuleController.getInstance(context);
            ruleController.setRules(
                RuleController.parseRules(context, R.xml.main_split_config)
            );
            return ruleController;
        }
      
        @NonNull
        @Override
        public List<Class<? extends Initializer<?>>> dependencies() {
            return Collections.emptyList();
        }
      }
      
  3. Kural tanımları için bir içerik sağlayıcı oluşturun.

    androidx.startup.InitializationProvider öğesini uygulama manifest dosyanıza <provider> olarak ekleyin. RuleController başlatıcınızın (SplitInitializer) uygulanmasına bir referans ekleyin:

    <!-- AndroidManifest.xml -->
    
    <provider android:name="androidx.startup.InitializationProvider"
        android:authorities="${applicationId}.androidx-startup"
        android:exported="false"
        tools:node="merge">
        <!-- Make SplitInitializer discoverable by InitializationProvider. -->
        <meta-data android:name="${applicationId}.SplitInitializer"
            android:value="androidx.startup" />
    </provider>
    

    InitializationProvider, uygulamanın onCreate() yöntemi çağrılmadan önce SplitInitializer öğesini keşfedip başlatır. Sonuç olarak bölme kuralları, uygulamanın ana etkinliği başladığında geçerli olur.

WindowManager API'si

Birkaç API çağrısıyla programlı bir şekilde etkinlik yerleştirme uygulayabilirsiniz. Herhangi bir etkinlik kullanıma sunulmadan önce kuralların geçerli olduğundan emin olmak için Application alt sınıfının onCreate() yöntemini kullanarak çağrılar yapın.

Programlı bir şekilde etkinlik grubu oluşturmak için aşağıdakileri yapın:

  1. Bölme kuralı oluşturun:

    1. Bölümü paylaşan etkinlikleri tanımlayan bir SplitPairFilter oluşturun:

      Kotlin

      val splitPairFilter = SplitPairFilter(
         ComponentName(this, ListActivity::class.java),
         ComponentName(this, DetailActivity::class.java),
         null
      )
      

      Java

      SplitPairFilter splitPairFilter = new SplitPairFilter(
         new ComponentName(this, ListActivity.class),
         new ComponentName(this, DetailActivity.class),
         null
      );
      
    2. Filtreyi bir filtre grubuna ekleyin:

      Kotlin

      val filterSet = setOf(splitPairFilter)
      

      Java

      Set<SplitPairFilter> filterSet = new HashSet<>();
      filterSet.add(splitPairFilter);
      
    3. Bölme için düzen özellikleri oluşturun:

      Kotlin

      val splitAttributes: SplitAttributes = SplitAttributes.Builder()
          .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
          .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
          .build()
      

      Java

      final SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();
      

      SplitAttributes.Builder, düzen özelliklerini içeren bir nesne oluşturur:

      • setSplitType: Kullanılabilir görüntüleme alanının her bir etkinlik kapsayıcısına nasıl ayrılacağını tanımlar. Oran bölme türü, birincil kapsayıcıya ayrılan kullanılabilir görüntüleme alanının oranını belirtir. İkincil kapsayıcı, kullanılabilir görüntüleme alanının geri kalanını kaplar.
      • setLayoutDirection: Etkinlik kapsayıcılarının, önce birincil kapsayıcı olmak üzere, birbirleriyle göreli olarak nasıl yerleştirildiğini belirtir.
    4. SplitPairRule oluşturma:

      Kotlin

      val splitPairRule = SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build()
      

      Java

      SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
          .setDefaultSplitAttributes(splitAttributes)
          .setMinWidthDp(840)
          .setMinSmallestWidthDp(600)
          .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
          .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
          .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
          .setClearTop(false)
          .build();
      

      SplitPairRule.Builder, kuralı oluşturur ve yapılandırır:

      • filterSet: Bir bölmeyi paylaşan etkinlikleri belirleyerek kuralın ne zaman uygulanacağını belirleyen bölünmüş çift filtreleri içerir.
      • setDefaultSplitAttributes: Düzen özelliklerini kurala uygular.
      • setMinWidthDp: Bölmeyi etkinleştiren minimum görüntü genişliğini (yoğunluktan bağımsız piksel cinsinden, dp cinsinden) ayarlar.
      • setMinSmallestWidthDp: Cihaz yönünden bağımsız olarak iki ekran boyutundan küçük olanın bölmeye imkan vermesi için gereken minimum değeri (dp cinsinden) ayarlar.
      • setMaxAspectRatioInPortrait: Etkinlik bölümlerinin görüntülendiği dikey yönde maksimum ekran en boy oranını (yükseklik:genişlik) ayarlar. Bir dikey ekranın en boy oranı maksimum en boy oranını aşarsa ekranın genişliğinden bağımsız olarak bölmeler devre dışı bırakılır. Not: Varsayılan değer 1,4'tür.Bu değer, çoğu tablette görev penceresinin tamamını dikey yönde kaplayan etkinliklere yol açar. Ayrıca bkz. SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT ve setMaxAspectRatioInLandscape. Yatay için varsayılan değer ALWAYS_ALLOW değeridir.
      • setFinishPrimaryWithSecondary: İkincil kapsayıcıdaki tüm etkinliklerin tamamlanmasının birincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini belirler. NEVER, ikincil kapsayıcıdaki tüm etkinlikler bittiğinde sistemin birincil etkinlikleri bitirmemesi gerektiğini belirtir (Etkinlikleri tamamlama bölümüne bakın).
      • setFinishSecondaryWithPrimary: Birincil kapsayıcıdaki tüm etkinliklerin tamamlanmasının ikincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini belirler. ALWAYS, birincil kapsayıcıdaki tüm etkinlikler bittiğinde sistemin ikincil kapsayıcıdaki etkinlikleri her zaman bitirmesi gerektiğini belirtir (Etkinlikleri tamamlama bölümüne bakın).
      • setClearTop: Kapsayıcıda yeni bir etkinlik başlatıldığında, ikincil kapsayıcıdaki tüm etkinliklerin tamamlanıp tamamlanmayacağını belirtir. Yanlış değeri, yeni etkinliklerin zaten ikincil kapsayıcıda bulunan etkinliklerin üzerine yığıldığını belirtir.
    5. WindowManager RuleController tekil örneğini alın ve kuralı ekleyin:

      Kotlin

      val ruleController = RuleController.getInstance(this)
      ruleController.addRule(splitPairRule)
      

      Java

      RuleController ruleController = RuleController.getInstance(this);
      ruleController.addRule(splitPairRule);
      
  2. İçerik mevcut olmadığında ikincil kapsayıcı için bir yer tutucu oluşturun:

    1. Yer tutucunun bir görev penceresi bölmesini paylaştığı etkinliği tanımlayan bir ActivityFilter oluşturun:

      Kotlin

      val placeholderActivityFilter = ActivityFilter(
          ComponentName(this, ListActivity::class.java),
          null
      )
      

      Java

      ActivityFilter placeholderActivityFilter = new ActivityFilter(
          new ComponentName(this, ListActivity.class),
          null
      );
      
    2. Filtreyi bir filtre grubuna ekleyin:

      Kotlin

      val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
      

      Java

      Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>();
      placeholderActivityFilterSet.add(placeholderActivityFilter);
      
    3. SplitPlaceholderRule oluşturun:

      Kotlin

      val splitPlaceholderRule = SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            Intent(context, PlaceholderActivity::class.java)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build()
      

      Java

      SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
            placeholderActivityFilterSet,
            new Intent(context, PlaceholderActivity.class)
          ).setDefaultSplitAttributes(splitAttributes)
           .setMinWidthDp(840)
           .setMinSmallestWidthDp(600)
           .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
           .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
           .setSticky(false)
           .build();
      

      SplitPlaceholderRule.Builder, kuralı oluşturur ve yapılandırır:

      • placeholderActivityFilterSet: Yer tutucu etkinliğinin ilişkili olduğu etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen etkinlik filtrelerini içerir.
      • Intent: Yer tutucu etkinliğinin başlatılmasını belirtir.
      • setDefaultSplitAttributes: Düzen özelliklerini kurala uygular.
      • setMinWidthDp: Bölmeye izin veren minimum görüntü genişliğini (yoğunluktan bağımsız piksel cinsinden, dp cinsinden) ayarlar.
      • setMinSmallestWidthDp: Cihaz yönünden bağımsız olarak iki ekran boyutundan küçük olanın bölünmeye izin vermesi gereken minimum değeri (dp cinsinden) ayarlar.
      • setMaxAspectRatioInPortrait: Etkinlik bölümlerinin görüntülendiği dikey yönde maksimum ekran en boy oranını (yükseklik:genişlik) ayarlar. Not: Varsayılan değer 1,4'tür.Bu, çoğu tablette etkinliklerin görev penceresini dikey yönde doldurmasıyla sonuçlanır. Ayrıca bkz. SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT ve setMaxAspectRatioInLandscape. Yatay için varsayılan değer ALWAYS_ALLOW değeridir.
      • setFinishPrimaryWithPlaceholder: Yer tutucu etkinliğini tamamlamanın birincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini belirler. HER ZAMAN, yer tutucu bittiğinde sistemin birincil kapsayıcıdaki etkinlikleri her zaman bitirmesi gerektiğini belirtir (İşlemleri tamamlama bölümüne bakın).
      • setSticky: Yer tutucunun yeterli minimum genişlikle bir bölmede ilk kez görünmesinden sonra, yer tutucu etkinliğinin küçük ekranlarda etkinlik yığınının üstünde görünüp görünmeyeceğini belirler.
    4. Kuralı WindowManager RuleController öğesine ekleyin:

      Kotlin

      ruleController.addRule(splitPlaceholderRule)
      

      Java

      ruleController.addRule(splitPlaceholderRule);
      
  3. Hiçbir zaman bir bölmenin parçası olmaması gereken etkinlikleri belirtin:

    1. Her zaman görev görüntüleme alanının tamamını kaplaması gereken bir etkinliği tanımlayan bir ActivityFilter oluşturun:

      Kotlin

      val expandedActivityFilter = ActivityFilter(
        ComponentName(this, ExpandedActivity::class.java),
        null
      )
      

      Java

      ActivityFilter expandedActivityFilter = new ActivityFilter(
        new ComponentName(this, ExpandedActivity.class),
        null
      );
      
    2. Filtreyi bir filtre grubuna ekleyin:

      Kotlin

      val expandedActivityFilterSet = setOf(expandedActivityFilter)
      

      Java

      Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>();
      expandedActivityFilterSet.add(expandedActivityFilter);
      
    3. ActivityRule oluşturun:

      Kotlin

      val activityRule = ActivityRule.Builder(expandedActivityFilterSet)
          .setAlwaysExpand(true)
          .build()
      

      Java

      ActivityRule activityRule = new ActivityRule.Builder(
          expandedActivityFilterSet
      ).setAlwaysExpand(true)
       .build();
      

      ActivityRule.Builder, kuralı oluşturur ve yapılandırır:

      • expandedActivityFilterSet: Bölümlerden hariç tutmak istediğiniz etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen etkinlik filtrelerini içerir.
      • setAlwaysExpand: Etkinliğin, görev penceresinin tamamını doldurup doldurmayacağını belirtir.
    4. Kuralı WindowManager RuleController öğesine ekleyin:

      Kotlin

      ruleController.addRule(activityRule)
      

      Java

      ruleController.addRule(activityRule);
      

Uygulamalar arası yerleştirme

Uygulamalar, Android 13 (API düzeyi 33) ve sonraki sürümlerde diğer uygulamalardaki etkinlikleri yerleştirebilir. Uygulamalar arası veya UID arası etkinlik yerleştirme, birden fazla Android uygulamasından etkinliklerin görsel entegrasyonunu sağlar. Sistem, ana makine uygulamasının etkinliğini ve başka bir uygulamanın yerleşik etkinliğini, tek uygulama etkinliği yerleştirmede olduğu gibi ekranda yan yana veya üstte ve altta gösterir.

Örneğin, Ayarlar uygulaması, Wallpaper Picker uygulamasından duvar kağıdı seçici etkinliğini yerleştirebilir:

Şekil 14. Yerleştirilmiş etkinlik olarak duvar kağıdı seçiciye sahip (sağda) Ayarlar uygulaması (soldaki menü).

Güven modeli

Diğer uygulamalardaki etkinlikleri yerleştiren ana makine işlemleri, yerleştirilmiş etkinliklerin boyut, konum, kırpma ve şeffaflık gibi sunumunu yeniden tanımlayabilir. Kötü amaçlı ana makineler, kullanıcıları yanıltmak ve tıklama korsanlığı veya başka kullanıcı arayüzünü engelleyen başka saldırılar oluşturmak için bu özelliği kullanabilir.

Uygulamalar arası etkinlik yerleştirme özelliğinin hatalı kullanımını önlemek için Android, uygulamaların kendi etkinliklerinin yerleştirilmesine izin vermeyi etkinleştirmesini zorunlu kılar. Uygulamalar, ana makineleri güvenilir veya güvenilmeyen olarak belirleyebilir.

Güvenilir ana makineler

Diğer uygulamaların uygulamanızdaki etkinlikleri yerleştirmesine ve bu etkinliklerin sunumunu tam olarak kontrol etmesine izin vermek için ana makine uygulamasının SHA-256 sertifikasını, uygulamanızın manifest dosyasındaki <activity> veya <application> öğelerinin android:knownActivityEmbeddingCerts özelliğinde belirtin.

android:knownActivityEmbeddingCerts değerini bir dize olarak ayarlayın:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
    ... />

veya birden fazla sertifika belirtmek için bir dize dizisi:

<activity
    android:name=".MyEmbeddableActivity"
    android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
    ... />

aşağıdaki gibi bir kaynağa başvuruda bulunuyor:

<resources>
    <string-array name="known_host_certificate_digests">
      <item>cert1</item>
      <item>cert2</item>
      ...
    </string-array>
</resources>

Uygulama sahipleri, Gradle signingReport görevini çalıştırarak SHA sertifika özeti alabilir. Sertifika özeti, ayırıcı iki nokta işareti içermeyen SHA-256 parmak izidir. Daha fazla bilgi edinmek için İmzalama raporu çalıştırma ve İstemcinizin Kimliğini Doğrulama sayfalarına göz atın.

Güvenilmeyen barındırıcılar

Herhangi bir uygulamanın, uygulamanızdaki etkinlikleri yerleştirmesine ve sunularını kontrol etmesine izin vermek için uygulama manifestindeki <activity> veya <application> öğelerinde android:allowUntrustedActivityEmbedding özelliğini belirtin. Örneğin:

<activity
    android:name=".MyEmbeddableActivity"
    android:allowUntrustedActivityEmbedding="true"
    ... />

Özelliğin varsayılan değeri olan false, uygulamalar arası etkinlik yerleştirmeyi engeller.

Özel kimlik doğrulama

Güvenilmeyen etkinlik yerleştirme risklerini azaltmak için ana makine kimliğini doğrulayan özel bir kimlik doğrulama mekanizması oluşturun. Ana makine sertifikalarını biliyorsanız kimlik doğrulamak için androidx.security.app.authenticator kitaplığını kullanın. Ana makine, etkinliğinizi yerleştirdikten sonra kimlik doğrulaması yaparsa gerçek içeriği görüntüleyebilirsiniz. Aksi takdirde, kullanıcıya işleme izin verilmediğini bildirebilir ve içeriği engelleyebilirsiniz.

Bir ana makinenin etkinliğinizi yerleştirip yerleştirmediğini kontrol etmek için Jetpack WindowManager kitaplığındaki ActivityEmbeddingController#isActivityEmbedded() yöntemini kullanın. Örneğin:

Kotlin

fun isActivityEmbedded(activity: Activity): Boolean {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity)
}

Java

boolean isActivityEmbedded(Activity activity) {
    return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity);
}

Minimum boyut kısıtlaması

Android sistemi, yerleşik etkinliklere, uygulama manifesti <layout> öğesinde belirtilen minimum yükseklik ve genişliği uygular. Bir uygulama minimum yükseklik ve genişliği belirtmezse sistem varsayılan değerleri (sw220dp) geçerli olur.

Ana makine, yerleştirilmiş kapsayıcıyı minimumdan daha küçük bir boyuta yeniden boyutlandırmaya çalışırsa yerleştirilmiş kapsayıcı tüm görev sınırlarını kaplayacak şekilde genişler.

<etkinlik-takma-adi>

Güvenilir veya güvenilmeyen etkinlik yerleştirmenin <activity-alias> öğesiyle çalışması için hedef etkinliğe takma ad yerine android:knownActivityEmbeddingCerts veya android:allowUntrustedActivityEmbedding uygulanmalıdır. Sistem sunucusunda güvenliği doğrulayan politika, takma ada değil, hedefte ayarlanan işaretlere dayanır.

Ana makine uygulaması

Barındırıcı uygulamalar, uygulamalar arası etkinlikleri yerleştirme işlemini, tek uygulama etkinliği yerleştirmesiyle aynı şekilde uygular. SplitPairRule ve SplitPairFilter veya ActivityRule ve ActivityFilter nesneleri, yerleştirilmiş etkinlikleri ve görev penceresi bölmelerini belirtir. Bölme kuralları, statik olarak XML olarak veya Jetpack WindowManager API çağrıları kullanılarak çalışma zamanında tanımlanır.

Bir ana makine uygulaması, uygulamalar arası yerleştirme özelliğinin etkinleştirilmediği bir etkinliği yerleştirmeye çalışırsa bu etkinlik görev sınırlarını kaplar. Bu nedenle ana makine uygulamalarının, hedef etkinliklerin uygulamalar arası yerleştirmeye izin verip vermediğini bilmesi gerekir.

Yerleştirilmiş bir etkinlik, aynı görevde yeni bir etkinlik başlatırsa ve yeni etkinlik, uygulamalar arası yerleştirme kapsamına dahil edilmezse etkinlik, yerleştirilmiş kapsayıcıya yer paylaşmak yerine tüm görev sınırlarını kaplar.

Bir ana makine uygulaması, etkinlikler aynı görevde başladığı sürece kendi etkinliklerini herhangi bir kısıtlama olmadan yerleştirebilir.

Bölme örnekleri

Tam pencereden ayır

Şekil 15. A etkinliği, yan tarafta B aktivitesini başlatır.

Yeniden düzenleme gerekmez. Bölme yapılandırmasını statik olarak veya çalışma zamanında tanımlayabilir ve daha sonra ek parametre olmadan Context#startActivity() yöntemini çağırabilirsiniz.

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Varsayılan olarak böl

Bir uygulamanın açılış sayfası büyük ekranlarda iki kapsayıcıya bölünecek şekilde tasarlandığında, kullanıcı deneyimi en iyi iki etkinliğin aynı anda oluşturulması ve sunulmasıdır. Bununla birlikte, kullanıcı birincil kapsayıcıdaki etkinlikle etkileşimde bulununcaya (örneğin, kullanıcı gezinme menüsünden bir öğe seçer) kadar bölmenin ikincil kapsayıcısında içerik kullanılamayabilir. İçerik, bölmenin ikincil kapsayıcısında görüntülenene kadar bir yer tutucu etkinliği boşluğu doldurabilir (yukarıdaki Yer tutucular bölümüne bakın).

Şekil 16. Grup, iki etkinliğin aynı anda açılmasıyla oluşturulur. Etkinliklerden biri yer tutucudur.

Bir yer tutucuyla bölme oluşturmak için bir yer tutucu oluşturun ve bunu birincil etkinlikle ilişkilendirin:

<SplitPlaceholderRule
    window:placeholderActivityName=".PlaceholderActivity">
    <ActivityFilter
        window:activityName=".MainActivity"/>
</SplitPlaceholderRule>

Bir uygulama amaç aldığında, hedef etkinlik, etkinlik bölmesinin ikincil parçası olarak gösterilebilir. Örneğin, bir listedeki bir öğeyle ilgili bilgileri içeren bir ayrıntı ekranı gösterme isteği. Küçük ekranlarda ayrıntılar tam görev penceresinde gösterilir. Daha büyük cihazlarda ise listenin yanında yer alır.

Şekil 17. Derin bağlantı ayrıntılı etkinliği küçük bir ekranda tek başına büyük ekranda liste etkinliğiyle birlikte gösterilir.

Başlatma isteği ana etkinliğe yönlendirilmeli ve hedef ayrıntı etkinliği de bölünmüş olarak başlatılmalıdır. Sistem, mevcut görüntü genişliğine göre doğru sunuyu (yığılmış veya yan yana) otomatik olarak seçer.

Kotlin

override fun onCreate(savedInstanceState Bundle?) {
    . . .
    RuleController.getInstance(this)
        .addRule(SplitPairRule.Builder(filterSet).build())
    startActivity(Intent(this, DetailActivity::class.java))
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    RuleController.getInstance(this)
        .addRule(new SplitPairRule.Builder(filterSet).build());
    startActivity(new Intent(this, DetailActivity.class));
}

Derin bağlantı hedefi, kullanıcının geri gezinme yığınında kullanabileceği tek etkinlik olabilir. Ayrıca, ayrıntılı etkinliği kapatmaktan ve yalnızca ana etkinliği bırakmaktan kaçınmak isteyebilirsiniz:

Liste ve ayrıntı etkinliğinin yan yana gösterildiği büyük ekran.
          Geri gezinme, ayrıntılı işlemleri kapatamadı ve liste etkinliğini ekranda bırakamadı.

Yalnızca ayrıntılı etkinliklerin yer aldığı küçük ekran. Geri gezinme, ayrıntılı işlemleri kapatamadı ve liste etkinliğini gösteremedi.

Bunun yerine, finishPrimaryWithSecondary özelliğini kullanarak her iki etkinliği de aynı anda tamamlayabilirsiniz:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".ListActivity"
        window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>

Aşağıdaki Yapılandırma özellikleri konusuna bakın.

Bölünmüş container'larda birden fazla etkinlik

Bölünmüş bir container'da birden fazla etkinliği yığmak, kullanıcıların derin içeriğe erişmesine olanak tanır. Örneğin, liste ayrıntılarının dağılımında kullanıcının bir alt ayrıntı bölümüne gitmesi ancak birincil etkinliği yerinde tutması gerekebilir:

Şekil 18. Etkinlik, görev penceresinin ikincil bölmesinde açılır.

Kotlin

class DetailActivity {
    . . .
    fun onOpenSubDetail() {
      startActivity(Intent(this, SubDetailActivity::class.java))
    }
}

Java

public class DetailActivity {
    . . .
    void onOpenSubDetail() {
        startActivity(new Intent(this, SubDetailActivity.class));
    }
}

Alt ayrıntı etkinliği, ayrıntı etkinliğinin en üstüne yerleştirilir ve gizlenir:

Kullanıcı daha sonra yığında geri giderek önceki ayrıntı düzeyine geri dönebilir:

Şekil 19. Etkinlik, grubun en üst kısmından kaldırıldı.

Etkinliklerin birbirinin üzerine yığılması, aynı ikincil kapsayıcıdaki bir etkinlikten etkinlikler başlatıldığında varsayılan davranıştır. Etkin bir bölmedeki birincil kapsayıcıdan başlatılan etkinlikler, etkinlik yığınının en üstündeki ikincil kapsayıcıda da sonuçlanır.

Yeni bir görevdeki etkinlikler

Bölünmüş görev penceresindeki etkinlikler yeni bir görevde etkinlik başlattığında, yeni görev bölmeyi içeren görevden ayrı olur ve tam pencerede gösterilir. Son Kullanılanlar ekranında iki görev gösterilir: Bölünmüş görev ve yeni görev.

Şekil 20. B etkinliğinden yeni bir görevde C etkinliğini başlatın.

Etkinlik değişimi

Etkinlikler ikincil kapsayıcı yığınında değiştirilebilir. Örneğin, birincil etkinlik üst düzey gezinme için kullanıldığında ve ikincil etkinlik seçilen bir hedef olduğunda. Üst düzey gezinmede yapılan her seçim, ikincil kapsayıcıda yeni bir etkinlik başlatmalı ve daha önce orada bulunan etkinlikleri veya etkinlikleri kaldırmalıdır.

Şekil 21. Birincil bölmedeki üst düzey gezinme etkinliği, ikincil bölmedeki hedef etkinliklerinin yerini alır.

Gezinme seçimi değiştiğinde uygulama, ikincil kapsayıcıdaki etkinliği tamamlamazsa bölme daraltıldığında (cihaz katlanmışken) geri gitme işlemi kafa karıştırıcı olabilir. Örneğin, birincil bölmede bir menünüz varsa ve A ve B ekranları ikincil bölmede yığılmış olarak gösteriliyorsa kullanıcı telefonu katladığında B, A'nın üzerinde, A da menünün üst kısmında yer alır. Kullanıcı B'den geri döndüğünde menü yerine A görünür.

Bu gibi durumlarda A ekranı arka gruptan kaldırılmalıdır.

Mevcut bir bölme üzerinde yeni bir kapsayıcıda yan tarafa başlarken varsayılan davranış, yeni ikincil kapsayıcıları en üste yerleştirmek ve eskilerini arka yığında tutmaktır. Bölmeleri, önceki ikincil kapsayıcıları clearTop ile temizleyecek ve yeni etkinlikleri normal şekilde başlatacak şekilde yapılandırabilirsiniz.

<SplitPairRule
    window:clearTop="true">
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenA"/>
    <SplitPairFilter
        window:primaryActivityName=".Menu"
        window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>

Kotlin

class MenuActivity {
    . . .
    fun onMenuItemSelected(selectedMenuItem: Int) {
        startActivity(Intent(this, classForItem(selectedMenuItem)))
    }
}

Java

public class MenuActivity {
    . . .
    void onMenuItemSelected(int selectedMenuItem) {
        startActivity(new Intent(this, classForItem(selectedMenuItem)));
    }
}

Alternatif olarak, aynı ikincil etkinliği kullanın ve birincil (menü) etkinlikten aynı örneğe çözümlenen ancak ikincil kapsayıcıda bir durum veya kullanıcı arayüzü güncellemesini tetikleyen yeni amaçlar gönderin.

Birden fazla bölüm

Uygulamalar, yan tarafa ek etkinlikler sunarak çok düzeyli, derin gezinme olanağı sunabilir.

İkincil kapsayıcıdaki bir etkinlik yan tarafta yeni bir etkinlik başlattığında, mevcut bölmenin üzerinde yeni bir bölme oluşturulur.

Şekil 22. B aktivitesi, C aktivitesini yanda başlatır.

Geri yığın, daha önce açılmış olan tüm etkinlikleri içerir. Böylece kullanıcılar C bittikten sonra A/B bölümüne gidebilir.

Bir yığındaki A, B ve C etkinlikleri. Etkinlikler yukarıdan aşağıya şu sırayla yığılır: C, B, A.

Yeni bir bölüm oluşturmak için mevcut ikincil kapsayıcının yan tarafında yeni etkinliği başlatın. Hem A/B hem de B/C bölümleri için yapılandırmaları bildirin ve C'yi normal olarak B'den başlatın:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
    <SplitPairFilter
        window:primaryActivityName=".B"
        window:secondaryActivityName=".C"/>
</SplitPairRule>

Kotlin

class B {
    . . .
    fun onOpenC() {
        startActivity(Intent(this, C::class.java))
    }
}

Java

public class B {
    . . .
    void onOpenC() {
        startActivity(new Intent(this, C.class));
    }
}

Bölünmüş durum değişikliklerine tepki verme

Bir uygulamadaki farklı etkinlikler, aynı işlevi gerçekleştiren kullanıcı arayüzü öğelerine sahip olabilir (örneğin, hesap ayarlarını içeren bir pencereyi açan bir kontrol).

Şekil 23. İşlevsel olarak aynı kullanıcı arayüzü öğelerine sahip farklı etkinlikler.

Ortak bir kullanıcı arayüzü öğesine sahip iki etkinlik bölünmüşse öğenin her iki etkinlikte de gösterilmesi gereksiz ve belki de kafa karıştırıcı olabilir.

Şekil 24. Etkinlik bölmesinde yinelenen kullanıcı arayüzü öğeleri.

Etkinliklerin ne zaman bölümlere ayrıldığını öğrenmek için SplitController.splitInfoList akışını kontrol edin veya bölünmüş durumdaki değişiklikler için SplitControllerCallbackAdapter ile bir işleyici kaydedin. Ardından, kullanıcı arayüzünü uygun şekilde ayarlayın:

Kotlin

val layout = layoutInflater.inflate(R.layout.activity_main, null)
val view = layout.findViewById<View>(R.id.infoButton)
lifecycleScope.launch {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance.
            .collect { list ->
                view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
            }
    }
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    . . .
    new SplitControllerCallbackAdapter(SplitController.getInstance(this))
        .addSplitListener(
            this,
            Runnable::run,
            splitInfoList -> {
                View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
                layout.findViewById(R.id.infoButton).setVisibility(
                    splitInfoList.isEmpty() ? View.VISIBLE : View.GONE);
            });
}

Eş yordamlar herhangi bir yaşam döngüsü durumunda başlatılabilir. Ancak kaynakları korumak için genellikle STARTED durumunda başlatılır. (Daha fazla bilgi için Yaşam döngüsüne duyarlı bileşenlerle Kotlin eşlerini kullanma başlıklı makaleyi inceleyin.)

Geri çağırmalar, bir etkinliğin durdurulduğu zamanlar da dahil olmak üzere herhangi bir yaşam döngüsü durumunda yapılabilir. İşleyiciler genellikle onStart() dilinde kayıtlı olmalı ve onStop() dilinde kayıtlı olmamalıdır.

Tam pencere kalıcı iletişim kutusu

Bazı etkinlikler, belirli bir işlem gerçekleştirilinceye kadar (ör. giriş ekranı etkinliği, politika onay ekranı veya hata mesajı) kullanıcıların uygulamayla etkileşimde bulunmasını engeller. Modal işlemlerin bölmede görünmesi önlenmelidir.

Bir etkinlik, genişletme yapılandırması kullanılarak görev penceresini her zaman doldurmaya zorlanabilir:

<ActivityRule
    window:alwaysExpand="true">
    <ActivityFilter
        window:activityName=".FullWidthActivity"/>
</ActivityRule>

Etkinlikleri tamamlama

Kullanıcılar, ekranın kenarından hızlıca kaydırarak, bölmenin her iki tarafındaki işlemleri tamamlayabilir:

Şekil 25. Kaydırma hareketiyle tamamlama etkinliği B.
Şekil 26. Kaydırma hareketiyle A etkinliğini tamamlama

Cihaz, hareketle gezinme yerine geri düğmesini kullanacak şekilde ayarlandıysa giriş, odaklanılan etkinliğe (en son dokunulan veya başlatılan aktivite) gönderilir.

Bir kapsayıcıdaki tüm etkinliklerin bitirilmesinin karşı kapsayıcı üzerindeki etkisi, bölünmüş yapılandırmasına bağlıdır.

Yapılandırma özellikleri

Bölmenin bir tarafındaki tüm etkinlikleri bitirmenin, bölmenin diğer tarafındaki etkinlikleri nasıl etkileyeceğini yapılandırmak için bölme çifti kuralı özelliklerini belirtebilirsiniz. Özellikler şunlardır:

  • window:finishPrimaryWithSecondary: İkincil kapsayıcıdaki tüm etkinliklerin tamamlanması birincil kapsayıcıdaki etkinlikleri nasıl etkiler?
  • window:finishSecondaryWithPrimary: Birincil kapsayıcıdaki tüm etkinliklerin tamamlanması ikincil kapsayıcıdaki etkinlikleri nasıl etkiler?

Özelliklerin olası değerleri şunlardır:

  • always: İlişkili kapsayıcıdaki etkinlikleri her zaman bitir
  • never: İlişkili kapsayıcıdaki etkinlikleri hiçbir zaman tamamlama
  • adjacent: İki kapsayıcı birbirine bitişik olduğunda (iki kapsayıcı yığıldığında değil) ilişkili kapsayıcıdaki etkinlikleri tamamlayın.

Örneğin:

<SplitPairRule
    <!-- Do not finish primary container activities when all secondary container activities finish. -->
    window:finishPrimaryWithSecondary="never"
    <!-- Finish secondary container activities when all primary container activities finish. -->
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Varsayılan yapılandırma

Bölünme işleminin bir kapsayıcısındaki tüm etkinlikler bittiğinde kalan kapsayıcı tüm pencereyi kaplar:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

A ve B etkinliklerini içeren bölme. A biter, B ise tüm pencereyi kaplar.

A ve B etkinliklerini içeren bölme. B sona erer ve A&#39;dan tüm pencereyi kaplar hale gelir.

Etkinlikleri birlikte tamamlayın

İkincil kapsayıcıdaki tüm etkinlikler tamamlandığında birincil kapsayıcıdaki etkinlikleri otomatik olarak tamamlayın:

<SplitPairRule
    window:finishPrimaryWithSecondary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

A ve B etkinliklerini içeren bölme. B tamamlanır ve görev penceresini boş bırakarak A da biter.

A ve B etkinliklerini içeren bölme. A işlemi tamamlanır ve B, görev penceresinde yalnız kalır.

Birincil kapsayıcıdaki tüm etkinlikler tamamlandığında ikincil kapsayıcıdaki etkinlikleri otomatik olarak tamamlayın:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

A ve B etkinliklerini içeren bölme. A işlemi tamamlanır ve görev penceresi boş bırakılarak B de biter.

A ve B etkinliklerini içeren bölme. B işini bitirir ve A&#39;yı görev penceresinde olduğu gibi bırakır.

Birincil veya ikincil kapsayıcıdaki tüm etkinlikler bittiğinde etkinlikleri birlikte bitirin:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

A ve B etkinliklerini içeren bölme. A işlemi tamamlanır ve görev penceresi boş bırakılarak B de biter.

A ve B etkinliklerini içeren bölme. B tamamlanır ve görev penceresini boş bırakarak A da biter.

Kapsayıcılarda birden çok etkinliği tamamlama

Birden fazla etkinlik bölünmüş bir kapsayıcıda yığılmışsa yığının en altında bir etkinliğin bitirilmesi üstteki etkinlikleri otomatik olarak tamamlamaz.

Örneğin, iki etkinlik ikincil kapsayıcıda ise, B'nin üstünde C:

B&#39;nin üzerine yığılmış C etkinliğini içeren ikincil etkinlik yığını, A etkinliğini içeren geçici etkinlik yığınının üzerine yığılır.

Bölmenin yapılandırması, A ve B etkinliklerinin yapılandırmasıyla tanımlanır:

<SplitPairRule>
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

üst etkinliği bitirdiğinizde bölünme korunmuş olur.

Birincil container&#39;da A etkinliği, ikincil kapsayıcıda B ve C etkinlikleri, B&#39;nin üzerine yığılmış C etkinlikleri ile bölünür. C işlemi biter, A ve B etkinlik bölümünde kalır.

İkincil kapsayıcının alt (kök) etkinliğini bitirmek, üzerindeki etkinlikleri kaldırmaz ve böylece bölme işlemini de korur.

Birincil container&#39;da A etkinliği, ikincil kapsayıcıda B ve C etkinlikleri, B&#39;nin üzerine yığılmış C etkinlikleri ile bölünür. B, A ve C&#39;yi etkinlik bölümünde bırakarak bitirir.

Etkinlikleri birlikte tamamlamaya yönelik tüm ek kurallar da (ör. ikincil etkinliği birincil işlemle bitirme) uygulanır:

<SplitPairRule
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Birincil container&#39;da A etkinliği ve ikincil kapsayıcıda B ile C etkinlikleri ile B&#39;nin üzerine yığılmış C ile bölün. A bitirir, B ve C de biter.

Bölme birincil ve ikincilyi birlikte bitirecek şekilde yapılandırıldığında:

<SplitPairRule
    window:finishPrimaryWithSecondary="always"
    window:finishSecondaryWithPrimary="always">
    <SplitPairFilter
        window:primaryActivityName=".A"
        window:secondaryActivityName=".B"/>
</SplitPairRule>

Birincil container&#39;da A etkinliği, ikincil kapsayıcıda B ve C etkinlikleri, B&#39;nin üzerine yığılmış C etkinlikleri ile bölünür. C işlemi biter, A ve B etkinlik bölümünde kalır.

Birincil container&#39;da A etkinliği, ikincil kapsayıcıda B ve C etkinlikleri, B&#39;nin üzerine yığılmış C etkinlikleri ile bölünür. B, A ve C&#39;yi etkinlik bölümünde bırakarak bitirir.

Birincil container&#39;da A etkinliği, ikincil kapsayıcıda B ve C etkinlikleri, B&#39;nin üzerine yığılmış C etkinlikleri ile bölünür. A bitirir, ayrıca B ve C bitirir.

Çalışma zamanında bölme özelliklerini değiştirin

Şu anda etkin olan ve görünür olan bir bölmenin özellikleri değiştirilemez. Bölme kurallarının değiştirilmesi, ek etkinlik başlatmaları ve yeni container'ları etkiler, ancak mevcut ve etkin bölmeleri etkilemez.

Etkin bölümlerin özelliklerini değiştirmek için bölmedeki yan etkinliği veya etkinlikleri tamamlayın ve yeni bir yapılandırmayla tekrar kenara başlatın.

Bölünmüş pencereden tam pencereye etkinlik çıkarma

Yan etkinliği tam pencerede gösteren yeni bir yapılandırma oluşturun, ardından aynı örneğe çözümlenen bir niyetle etkinliği yeniden başlatın.

Çalışma zamanında bölünmüş desteği kontrol edin

Etkinlik yerleştirme özelliği, Android 12L (API düzeyi 32) ve sonraki sürümlerde desteklenir ancak önceki platform sürümlerini çalıştıran bazı cihazlarda da kullanılabilir. Çalışma zamanında özelliğin kullanılabilirliğini kontrol etmek için SplitController.splitSupportStatus özelliğini veya SplitController.getSplitSupportStatus() yöntemini kullanın:

Kotlin

if (SplitController.getInstance(this).splitSupportStatus ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

Java

if (SplitController.getInstance(this).getSplitSupportStatus() ==
     SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
     // Device supports split activity features.
}

Bölmeler desteklenmiyorsa etkinlikler, etkinlik yığınının üzerinde başlatılır (etkinlik dışı yerleştirme modeline göre).

Sistemin geçersiz kılmasını engelleyin

Android cihaz üreticileri (orijinal donanım üreticileri veya OEM'ler), etkinlik yerleştirmeyi cihaz sisteminin bir işlevi olarak uygulayabilir. Sistem, çoklu etkinlik uygulamaları için bölme kuralları belirleyerek uygulamaların aralık oluşturma davranışını geçersiz kılar. Sistem geçersiz kılma, çok etkinlikli uygulamaları sistem tanımlı etkinlik yerleştirme moduna zorlar.

Sistem etkinliği yerleştirme, uygulamada herhangi bir değişiklik yapmadan list-detail gibi çok bölmeli düzenler aracılığıyla uygulama sunumunu iyileştirebilir. Ancak, sistemin etkinlik yerleştirme özelliği de yanlış uygulama düzenlerine, hatalara veya uygulama tarafından uygulanan etkinlik yerleştirmeyle çakışmalara yol açabilir.

Uygulamanız, uygulama manifest dosyasında bir mülk ayarlayarak sistem etkinliğinin yerleştirilmesini engelleyebilir veya buna izin verebilir. Örneğin:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application>
        <property
            android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
            android:value="true|false" />
    </application>
</manifest>

Özellik adı, Jetpack WindowManager WindowProperties nesnesinde tanımlanır. Uygulamanızda etkinlik yerleştirme işlevi uygulanıyorsa veya sistemin, etkinlik yerleştirme kurallarını uygulamanıza uygulamasını başka bir şekilde engellemek istiyorsanız değeri false olarak ayarlayın. Sistemin uygulamanıza sistem tanımlı etkinlik yerleştirmesine izin vermek için değeri true olarak ayarlayın.

Sınırlamalar, kısıtlamalar ve uyarılar

  • Yalnızca görevdeki kök etkinliğin sahibi olarak tanımlanan görevin ana makine uygulaması, görevdeki diğer etkinlikleri düzenleyebilir ve yerleştirebilir. Yerleştirme ve bölme işlemlerini destekleyen etkinlikler farklı bir uygulamaya ait bir görevde çalışırsa yerleştirme ve bölme işlemleri bu etkinliklerde çalışmaz.
  • Etkinlikler yalnızca tek bir görev içinde düzenlenebilir. Bir etkinlik yeni bir görevde başlatıldığında, etkinlik her zaman mevcut bölümlerin dışındaki yeni bir genişletilmiş pencereye yerleştirilir.
  • Yalnızca aynı süreçteki etkinlikler organize edilebilir ve bölümlere ayrılabilir. Farklı işlemlerdeki etkinlikler hakkında bilgi edinmenin bir yolu olmadığından SplitInfo geri çağırma özelliği yalnızca aynı işleme ait etkinlikleri raporlar.
  • Her çift veya tekil etkinlik kuralı, yalnızca kural kaydedildikten sonra gerçekleşen etkinlik başlatmalar için geçerlidir. Şu anda mevcut bölmeleri veya görsel özelliklerini güncellemenin bir yolu yoktur.
  • Bölünmüş çift filtre yapılandırması, etkinlikleri tam olarak başlatırken kullanılan niyetlerle eşleşmelidir. Eşleşme, başvuru sürecinden yeni bir etkinlik başlatıldığı anda gerçekleşir. Bu nedenle, örtülü amaçlar kullanılırken sistem işleminin ilerleyen aşamalarında çözümlenen bileşen adları hakkında bilgi sahibi olmayabilir. Lansman sırasında bir bileşen adı bilinmiyorsa bunun yerine joker karakter ("*/*") kullanılabilir ve amaç eylemine göre filtreleme yapılabilir.
  • Şu anda etkinlikleri, oluşturulduktan sonra kapsayıcılar arasında veya bölmelerin içine ve dışına taşımanın bir yolu yoktur. Bölmeler yalnızca eşleşen kurallara sahip yeni etkinlikler başlatıldığında WindowManager kitaplığı tarafından oluşturulur ve bölmeler, bölünmüş kapsayıcıdaki son etkinlik tamamlandığında silinir.
  • Yapılandırma değiştiğinde etkinlikler yeniden başlatılabilir. Böylece, bir bölme oluşturulduğunda veya kaldırıldığında ve etkinlik sınırları değiştiğinde etkinlik, önceki örneğin tamamen yok edilip yenisinin oluşturulmasından geçebilir. Sonuç olarak, uygulama geliştiricileri yaşam döngüsü geri çağırmalarından yeni etkinlikler başlatmak gibi konularda dikkatli olmalıdır.
  • Cihazlar, etkinlik yerleştirmeyi desteklemek için pencere uzantıları arayüzüne sahip olmalıdır. Android 12L (API düzeyi 32) veya sonraki sürümleri çalıştıran büyük ekranlı cihazların neredeyse tamamı arayüze sahiptir. Ancak birden fazla etkinlik çalıştıramayan bazı büyük ekranlı cihazlarda pencere uzantıları arayüzü bulunmaz. Büyük ekranlı bir cihaz çoklu pencere modunu desteklemiyorsa, etkinlik yerleştirmeyi desteklemiyor olabilir.

Ek kaynaklar