Etkinlik yerleştirme

Etkinlik yerleştirme, bir öğeyi bölerek büyük ekranlı cihazlarda uygulamaları optimize eder. uygulamanın görev penceresinin iki etkinlik veya aynı iki örneğin arasında etkinliği'ne dokunun.

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

Uygulamanız birden fazla etkinlikten oluşuyorsa etkinlik yerleştirme özelliği sayesinde Tabletler, katlanabilir cihazlar ve ChromeOS cihazlarda gelişmiş bir kullanıcı deneyimi sağlar.

Etkinlik yerleştirme için kod yeniden düzenlemesi gerekmez. Bir XML yapılandırma dosyası oluşturarak veya Jetpack WindowManager API çağrıları yaparak uygulamanızın etkinliklerini nasıl (yan yana veya yığılmış olarak) göstereceğini siz belirlersiniz.

Küçük ekran desteği otomatik olarak devam eder. Uygulamanız küçük ekranlı bir cihazda olduğunda etkinlikler birbirinin üzerine yığılır. Şu tarihte: etkinlikler yan yana görüntülenir. Sistem, sunumu oluşturduğunuz yapılandırmaya göre belirler. Dallanma mantığı gerekmez.

Etkinlik yerleştirme, cihaz yön değişikliklerini karşılar ve katlanabilir cihazlarda sorunsuz bir şekilde çalışır. Cihaz katlandığında ve açıldığında etkinlikleri yığınlar ve yığınları dağıtır.

Etkinlik yerleştirme, Android 12L çalıştıran büyük ekranlı cihazların çoğunda desteklenir (API düzeyi 32) ve sonraki sürümler.

Görev penceresini böl

Etkinlik yerleştirme, uygulama görev penceresini birincil ve ikincil olmak üzere iki kapsayıcıya böler. Kapsayıcılarda, ana etkinlikten veya kapsayıcılarda bulunan diğer etkinliklerden başlatılan etkinlikler bulunur.

Etkinlikler, başlatıldıkları sırada ikincil kapsayıcıya yığılır ve küçük ekranlarda ikincil kapsayıcı, birincil kapsayıcının üzerine yığılır. Bu nedenle etkinlik yığma ve geri gezinme, uygulamanızda zaten yerleşik olan etkinliklerin sıralamasıyla tutarlıdır.

Etkinlik yerleştirme, etkinlikleri çeşitli şekillerde görüntülemenize olanak tanır. Sizin Uygulama, iki etkinliği yan yana başlatarak görev penceresini bölebilir. aynı anda:

Şekil 2. Yan yana iki etkinlik.

Görev penceresinin tamamını kaplayan bir etkinlik, yanında yeni bir etkinlik başlatarak da bölme oluşturabilir:

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

Zaten bölünmüş olan ve bir görev penceresini paylaşan etkinlikler başlatılabilir. aşağıdaki şekillerde kullandığınızdan emin olun:

  • Başka bir aktivitenin yanında:

    Şekil 4. A Etkinliği, B aktivitesinin üzerinde yan tarafta C aktivitesini başlatır.
  • Yana doğru kaydırın ve bölümü yana doğru kaydırarak önceki birincil etkinlik:

    Şekil 5. B etkinliği, C etkinliğini yan tarafta başlatır ve bölünmüş ekranı yana doğru kaydırır.
  • Hemen bir etkinlik başlatın; Yani aynı etkinlik yığınında:

    Şekil 6. B Etkinliği, C etkinliğini ekstra intent işareti olmadan başlatır.
  • Aynı görevde bir etkinlik tam penceresini başlatma:

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

Geri gitme

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

  • Bir araya gelme: Etkinlikler birbiriyle ilgiliyse ve birinin gösterilmemesi gerekiyorsa yoksa geri gezinme her ikisini de tamamlayacak şekilde yapılandırılabilir.
  • Tek başına devam etme: Etkinlikler tamamen bağımsızysa, etkinliği görev penceresindeki başka bir etkinliğin durumunu etkilemez.

Düğme gezinme kullanılırken geri etkinliği, odaklanılan son etkinliğe gönderilir.

Harekete dayalı gezinme için:

  • Android 14 (API düzeyi 34) ve önceki sürümler: Geri etkinlik Hareketin gerçekleştiği etkinlik. Kullanıcılar, sayfayı sol tarafından kaydırdığında sol taraftaki etkinliğe gönderilir. bölmesini seçebilirsiniz. Kullanıcılar, sayfanın sağ tarafından kaydırıldığında ekranında, geri etkinliği sağ bölmedeki etkinliğe gönderilir.

  • Android 15 (API düzeyi 35) ve sonraki sürümler

    • Aynı uygulamadaki birden fazla etkinlikle çalışırken hareket, kaydırma yönünden bağımsız olarak en üstteki etkinliği sonlandırır ve daha birleşik bir deneyim sunar.

    • Farklı uygulamalardan iki etkinliğin yer aldığı senaryolarda (yer paylaşımı), geri etkinliği, düğme gezinmesinin davranışıyla uyumlu olacak şekilde odaktaki son etkinliğe yönlendirilir.

Çok bölmeli düzen

Jetpack WindowManager, Android 12L (API düzeyi 32) veya sonraki sürümleri çalıştıran büyük ekranlı cihazlarda ve daha eski platform sürümlerini çalıştıran bazı cihazlarda çok bölmeli düzeni yerleştiren bir etkinlik oluşturmanıza olanak tanır. SlidingPaneLayout gibi fragmentler veya görünüme dayalı düzenler yerine birden fazla etkinliğe dayalı mevcut uygulamalar, kaynak kodunu yeniden düzenlemeden büyük ekranda daha iyi bir kullanıcı deneyimi sağlayabilir.

Liste ayrıntılarına bölünme, yaygın bir örnektir. Yüksek kaliteli bir sunum sağlamak için sistem liste etkinliğini başlatır, ardından uygulama hemen ayrıntı etkinliğini başlatır. Geçiş sistemi, her iki etkinlik de çizilene kadar bekler ve ardından bunları birlikte gösterir. Kullanıcı açısından, ve aktivitelerin bir arada başlatılması gerekir.

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

Bölünmüş özellikler

Görev penceresinin bölünmüş kapsayıcılar arasında nasıl orantılı olacağını belirtebilirsiniz ve container'ların birbirlerine göre nasıl düzenleneceğini öğreneceğiz.

Bir 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ısıdır.
  • splitLayoutDirection: Bölünmüş kapsayıcıların birbirine göre nasıl yerleştirileceğini belirtir. Değerler şunlardır:
    • ltr: Soldan sağa
    • rtl: Sağdan sola
    • locale: Yerel ayardan ltr veya rtl belirlenir

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

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

Örnekler için WindowManager API bölümüne bakın.

Şekil 9. Soldan sağa doğru farklı bölme oranlarıyla yerleştirilmiş iki etkinlik bölümü.

Yer tutucular

Yer tutucu etkinlikleri, belirli bir alanın bir alanını kaplayan boş ikincil etkinlik dağılımı. Amaç, bu etkinlikleri içerik barındıran başka bir etkinlikle değiştirmek. Örneğin, bir yer tutucu etkinliği liste ayrıntıları düzeninde bölünmüş bir etkinliğin ikincil tarafı, liste seçilir ve bu noktada seçilen liste öğesinin bilgileri yer tutucunun yerini alır.

Varsayılan olarak sistem, yer tutucuları yalnızca etkinlik bölme işlemi için yeterli alan olduğunda gösterir. Ekran boyutu, bölünmüş ekranı görüntülemek için çok küçük bir genişlik veya yüksekliğe değiştiğinde yer tutucular otomatik olarak sonlandırılır. Yer varsa, sistem, yer tutucuyu sıfırlanmış durumda yeniden başlatır.

Şekil 10. Katlanabilir cihaz katlanabilir ve açılır. Yer tutucu etkinlik tamamlanır ve ekran boyutu değiştikçe yeniden oluşturulur.

Ancak stickyPlaceholder özelliği bir SplitPlaceholderRule veya SplitPlaceholder.Builder için setSticky() yöntemi, varsayılan davranıştır. Özellik veya yöntem bir true değeri belirttiğinde sistem yer tutucuyu, görev penceresindeki en üst etkinlik olarak görüntüler. Ekran, iki bölmeli ekrandan tek bölmeli bir ekran olacak şekilde yeniden boyutlandırılır (örnek için Bölünmüş yapılandırma bölümüne bakın).

Şekil 11. Katlanabilir cihazın katlanması ve açılması. 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 düzen için yeterince büyük (örneğin, katlanabilir büyük ekran cihaz tablet boyutundan telefon boyutuna kadar katlanır veya uygulama penceresi çoklu pencere modu), ikincil bölmedeki yer tutucu olmayan etkinlikleri gösterir. görev penceresi, birincil bölmedeki etkinliklerin üzerine yerleştirilir.

Yer tutucu etkinlikler yalnızca bölme için yeterli ekran 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 gelirse yer tutucu yeniden oluşturulur. (Yer tutucular bölümüne bakın.)

WindowManager, ikincil bölmede yer alan etkinlikleri birincil bölmede yer alan etkinliklerin üzerine z-sıralı olarak yerleştirdiği için etkinliklerin yığılması mümkündür.

İkincil bölmede birden fazla etkinlik

B etkinliği, ek intent işaretleri olmadan C etkinliğini yerinde başlatır:

A, B ve C etkinliklerini içeren etkinlik bölümü; C üst üste yığılmış
          B harfinin üstündedir.

Bu işlem sonucunda, aynı görevdeki etkinliklerin z-sıralı düzeni aşağıdaki gibi olur:

B'nin üstünde yığılmış C etkinliğini içeren ikincil etkinlik yığını.
          İkincil yığın, temel etkinlik yığınının üzerine yığılıyor
          içeren bir örnektir.

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

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

Küçük pencerede geriye gittiğinizde, etkinliklerin üzerine yığılmış etkinlikler arasında gezinirsiniz.

Görev penceresi yapılandırması, birden çok bölme bulunması halinde, etkinlikler tekrar yan yana görüntülenir.

Yığılmış bölmeler

B etkinliği, C etkinliğini yan tarafta başlatır ve bölünmüş ekranı yana doğru kaydırır:

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

Sonuç, aynı görevdeki etkinliklerin z-sıralamasıdır:

A, B ve C etkinlikleri tek bir yığında. Etkinlikler üst üste yığılır
          yukarıdan aşağıya doğru sırayla: C, B, A.

Daha küçük bir görev penceresinde, uygulama C'de tek bir etkinliğe küçültülür üst:

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önde kısıtlamasına olanak tanır. Kullanıcı deneyimini iyileştirmek için tabletler ve katlanabilir cihazlar gibi büyük ekranlı cihazlarda, cihaz üreticileri (OEM'ler) ekran yönü isteklerini yoksayabilir ve dikey modda sinemaskop efekti uygulayabilir. dikey ekranlarda yatay yönde veya dikey ekranlarda yatay yönde.

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

Benzer şekilde, OEM'ler etkinlik yerleştirme etkinleştirildiğinde cihazları büyük ekranlarda (genişlik ≥ 600 dp) yatay yönde sabit dikey aktiviteler için sinemaskoplu olacak şekilde özelleştirebilir. Sabit dikey etkinlik ikinci bir aktivite başlattığında cihaz bu iki etkinliği iki bölmeli bir ekranda yan yana gösterebilir.

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

Cihazları, uygulamanızın etkinlik yerleştirmeyi desteklediğini bildirmek için uygulama manifest dosyanıza her zaman android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED mülkünü ekleyin (Bölünmüş yapılandırma bölümüne bakın). OEM tarafından özelleştirilen cihazlar, sabit dikey etkinliklerin sinemaskop modunda gösterilip gösterilmeyeceğini belirleyebilir.

Bölme yapılandırması

Bölme kuralları etkinlik bölümlerini yapılandırır. Bölme kurallarını XML'de tanımlarsınız yapılandırma dosyasını kullanarak veya Jetpack WindowManager API'yi kurarak çağrısının en iyi yolu.

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

Aşağıdakileri yapın:

  1. Uygulamanızın modül düzeyine en yeni WindowManager kitaplığı bağımlılığını ekleyin build.gradle dosyası, örneğin:

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

    WindowManager kitaplığı etkinlik için gereken tüm bileşenleri sağlar bir öğedir.

  2. Sistemi, uygulamanızın etkinlik yerleştirme özelliğini uyguladığını bilgilendirin.

    android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED mülkünü uygulama manifest dosyasının <application> öğesine ekleyin ve 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, mülk manifest dosyasına eklenip true olarak ayarlanmazsa etkinlik yerleştirme bölmelerini devre dışı bırakılır.

    Ayrıca cihaz üreticileri, uygulamaları için de kullanabilirsiniz. Örneğin, cihazlar ikinci bir etkinlik başladığında etkinliği iki bölmeli bir düzene geçiş için yönlendirmek amacıyla yatay ekranlarda yalnızca dikey olan bir etkinliği sinemaskop şeklinde gösterebilir (Sabit dikey yön bölümüne bakın).

XML yapılandırması

Etkinlik yerleştirme özelliğinin XML tabanlı bir uygulamasını oluşturmak için şu adımları uygulayın:

  1. Aşağıdakileri gerçekleştiren bir XML kaynak dosyası oluşturun:

    • Bir bölümü paylaşan etkinlikleri tanımlar
    • Bölme seçeneklerini yapılandırır.
    • İçerik mevcut olmadığında bölünmüş içeriğin ikincil kapsayıcısı için bir yer tutucu oluşturur
    • Hiçbir zaman bir bölme işleminin parçası olmaması gereken etkinlikleri belirtir.

    Örnek:

    <!-- 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 sunar. Jetpack Başlangıç kitaplığı Initializer, XML dosyasını kuralların geçerli olması için uygulama başlangıcında RuleController yardımcı olur.

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

    1. Modül düzeyinize en yeni Jetpack Startup kitaplığı bağımlılığını ekleyin build.gradle dosyası, ö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 kimliğini (main_split_config.xml) RuleController.parseRules() yöntemine ileterek bölme kurallarını RuleController için kullanılabilir hale getirir.

      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 ekleyin <provider> olarak. RuleController başlatıcınızın SplitInitializer uygulanmasına 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, SplitInitializer öncesini bulup başlatır uygulamanın onCreate() yöntemi çağrılır. Sonuç olarak, bölme kuralları ana etkinliği başladığında etkili olur.

WindowManager API'sı

Etkinlik yerleştirmeyi birkaç API çağrısıyla programatik olarak uygulayabilirsiniz. Kuralların herhangi bir etkinlik başlatılmadan önce geçerli olduğundan emin olmak için Application alt sınıfının onCreate() yönteminde çağrıları yapın.

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

  1. Bölme kuralı oluşturun:

    1. Bir SplitPairFilter oluşturun bir grafik öğesi seçin:

      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 içeren bir nesne oluşturur özellikler:

      • setSplitType(): Mevcut ekran alanının her etkinlik kapsayıcısına nasıl ayrıldığını tanımlar. Oran bölme türü, birincil kapsayıcıya ayrılan kullanılabilir ekran alanının oranını belirtir. İkincil kapsayıcı, kullanılabilir ekran alanının geri kalanını kaplar.
      • setLayoutDirection(): Etkinlik kapsayıcılarının birbirine göre nasıl düzenlendiğini belirtir. Önce birincil kapsayıcı.
    4. Bir SplitPairRule oluşturun:

      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: Bölme paylaşan etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen bölme çifti filtreleri içerir.
      • setDefaultSplitAttributes(): Düzen özelliklerini kuralı.
      • setMinWidthDp(): Bölünmeyi etkinleştiren minimum ekran genişliğini (yoğunluktan bağımsız piksel cinsinden, dp) ayarlar.
      • setMinSmallestWidthDp(): Kullanılan minimum değeri (dp cinsinden) iki ekran boyutundan daha küçük olanı, cihaz yönünden bağımsız olarak bölebilirsiniz.
      • setMaxAspectRatioInPortrait(): Etkinlik bölmelerinin gösterildiği dikey yönde maksimum ekran en boy oranını (yükseklik:genişlik) ayarlar. 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, etkinliklerin çoğu tablette dikey yönde görev penceresinin tamamını kaplamasına neden olur. Şu kaynakları da inceleyin SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT ve setMaxAspectRatioInLandscape(). Varsayılan değer: yatay ALWAYS_ALLOW.
      • setFinishPrimaryWithSecondary(): Tüm işlemlerin ne kadar tamamlanacağını ayarlar etkinlikler, ikincil kapsayıcıdaki etkinlikleri etkiler. birincil kapsayıcı değildir. NEVER, sistemin tamamlanmaması gerektiğini belirtir tüm etkinliklerin gerçekleştirildiği birincil aktiviteler (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 etkilediğini belirler. ALWAYS, sistemin her zaman tüm etkinlikler gerçekleştirildiğinde, ikincil kapsayıcıdaki etkinlikleri (bkz. Etkinlikleri tamamlayın).
      • setClearTop(): Tüm etkinliklerin şurada yeni bir etkinlik başlatıldığında ikincil kapsayıcı tamamlanır: kaldıracak. false değeri, yeni etkinliklerin zaten ikincil kapsayıcıda bulunan etkinliklerin üzerine yerleştirilir.
    5. WindowManager RuleController sınıfının 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. Aşağıdaki durumlarda ikincil kapsayıcı için bir yer tutucu oluşturun içerik kullanılamıyor:

    1. Yer tutucunun 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. Bir metin oluştur: SplitPlaceholderRule:

      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ölünmeye izin veren minimum ekran genişliğini (yoğunluktan bağımsız piksel cinsinden, dp) ayarlar.
      • setMinSmallestWidthDp(): Cihaz yönüne bakılmaksızın bölünmeye izin vermek için iki ekran boyutundan küçük olanın sahip olması gereken minimum değeri (dp cinsinden) belirler.
      • setMaxAspectRatioInPortrait(): Etkinlik bölmelerinin gösterildiği dikey yönde maksimum ekran en boy oranını (yükseklik:genişlik) belirler. Not: Varsayılan değer 1,4'tür. Bu değer, çoğu tablette etkinliklerin görev penceresini dikey yönde doldurmasına neden olur. Ayrıca SPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT ve setMaxAspectRatioInLandscape() sayfalarına da göz atın. Yatay için varsayılan değer ALWAYS_ALLOW şeklindedir.
      • setFinishPrimaryWithPlaceholder(): Yer tutucu etkinliğinin tamamlanmasının birincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini belirler. HER ZAMAN sistemin her zaman birincil kapsayıcıdaki etkinlikleri bitirmek için bitirir (İşlemleri tamamlama bölümüne bakın).
      • setSticky(): Yer tutucu etkinliğin olup olmadığını belirler. küçük ekranlarda etkinlik yığınının en üstünde görünür. yer tutucu, ilk olarak yeterli minimum değerle bir bölümde göründü dokunun.
    4. Kuralı WindowManager'a RuleController ekleyin:

      Kotlin

      ruleController.addRule(splitPlaceholderRule)

      Java

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

    1. Yapılması gereken bir etkinliği tanımlayan bir ActivityFilter oluşturun: her zaman tüm görev görüntüleme alanını kaplar:

      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ümlere dahil etmek istemediğ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 içine ekleyin:

      Kotlin

      ruleController.addRule(activityRule)

      Java

      ruleController.addRule(activityRule);

Uygulamalar arası yerleştirme

Android 13 (API düzeyi 33) ve sonraki sürümlerde uygulamalar, diğer uygulamalardaki etkinlikleri yerleştirebilir. Uygulamalar arası veya UID'ler arası etkinlik yerleştirme Birden fazla Android uygulamasındaki etkinliklerin görsel entegrasyonunu sağlar. İlgili içeriği oluşturmak için kullanılan sistem, ana makine uygulamasının bir etkinliğini ve şuradan yerleştirilmiş bir etkinliği görüntüler: ekranda tıpkı tek bir uygulamada olduğu gibi yan yana veya üstten alta başka bir uygulama etkinliği yerleştirme işlemidir.

Örneğin, Ayarlar uygulaması, duvar kağıdı seçme uygulaması:

Şekil 14. Yerleşik etkinlik olarak duvar kağıdı seçicinin (sağda) yer aldığı Ayarlar uygulaması (soldaki menü).

Güven modeli

Diğer uygulamalardaki etkinlikleri yerleştiren ana makine işlemleri, ve boyut, konum, kırpma ve kırpma dahil olmak üzere yerleştirilmiş şeffaflık. Kötü amaçlı barındırıcılar, bu özelliği kullanarak kullanıcıları yanıltabilir ve tıklama korsanlığı veya kullanıcı arayüzünü iyileştirmeye yönelik başka saldırılar oluşturur.

Uygulamalar arası etkinlik yerleştirme özelliğinin kötüye kullanılmasını önlemek için Android, yerleştirmeye izin vermesidir. Uygulamalar, ana makineleri güvenilir olarak atayabilir güvenilir olmayabilir.

Güvenilir ana makineler

Diğer uygulamaların, uygulamanızdaki etkinliklerin sunumunu yerleştirmesine ve tamamen kontrol etmesine izin vermek için uygulamanızın manifest dosyasının <activity> veya <application> öğelerinin android:knownActivityEmbeddingCerts özelliğinde barındıran uygulamanın SHA-256 sertifikasını belirtin.

android:knownActivityEmbeddingCerts değerini 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 referans verir:

<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 özetini alabilir. Sertifika özeti, iki nokta işareti ayırıcısı olmayan SHA-256 parmak izidir. Daha fazla bilgi için İmzalama raporu çalıştırma başlıklı makaleyi inceleyin. İstemcinizin Kimliğini Doğrulama.

Güvenilmeyen ana makineler

Herhangi bir uygulamanın, uygulamanızın etkinliklerini yerleştirmesine ve sunumunu kontrol etmesine izin vermek için uygulama manifest'indeki <activity> veya <application> öğelerinde android:allowUntrustedActivityEmbedding özelliğini belirtin. Örneğin:

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

Özniteliğin varsayılan değeri false (yanlış) olduğundan uygulama içi etkinliklerin yerleştirilmesi engellenir.

Özel kimlik doğrulama

Güvenilir olmayan etkinlik yerleştirme risklerini azaltmak için özel bir ana makine kimliğini doğrulayan kimlik doğrulama mekanizmasıdır. Ana makineyi tanıyorsanız androidx.security.app.authenticator kitaplığını kullanarak kimlik doğrulama. Ana makine, etkinliğinizi yerleştirdikten sonra kimlik doğrulaması yaparsa şunları yapabilirsiniz: gerçek içeriği gösterir. Aksi takdirde, kullanıcıya işleme izin verilmediğini bildirebilir ve içeriği engelleyebilirsiniz.

Şu listeden ActivityEmbeddingController#isActivityEmbedded() yöntemini kullanın: Jetpack WindowManager kitaplığını kullanarak bir ana makinenin etkinlik, ö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, uygulama manifest'inde <layout> öğesinde belirtilen minimum yüksekliği ve genişliği yerleşik etkinliklere uygular. Bir uygulamada minimum yükseklik ve genişlik belirtilmezse sistem varsayılan değerleri geçerli olur (sw220dp).

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

<activity-alias>

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 sunucusundaki güvenliği doğrulayan politika, takma ada göre değil, hedefte belirlenen bayraklara göre belirlenir.

Ana makine uygulaması

Barındıran uygulamalar, uygulama içi etkinlik yerleştirmeyi tek uygulamalı etkinlik yerleştirmeyle aynı şekilde uygular. SplitPairRule ve SplitPairFilter veya ActivityRule ve ActivityFilter nesneleri, yerleşik etkinlikleri ve görev penceresi bölmelerini belirtir. Bölme kuralları XML'de statik olarak veya Jetpack WindowManager API çağrıları kullanılarak çalışma zamanında tanımlanır.

Bir barındırıcı uygulama, uygulamalar arası yerleştirmeyi etkinleştirmemiş bir etkinliği yerleştirmeye çalışırsa etkinlik, görev sınırlarının tamamını kaplar. Sonuç olarak, ana makine uygulamalarının, hedef etkinliklerin uygulamalar arası uygulamalara izin verip vermediğini bilmesi gerekir. bir öğedir.

Yerleştirilmiş bir etkinlik aynı görevde yeni bir etkinlik başlatırsa ve yeni etkinlik uygulamalar arası yerleştirmeyi etkinleştirmemişse etkinlik, yerleştirilmiş kapsayıcıdaki etkinliği yer paylaşımı yapmak yerine görev sınırlarının tamamını kaplar.

Barındıran uygulama, etkinlikler aynı görevde başlatıldığı sürece kendi etkinliklerini kısıtlama olmadan yerleştirebilir.

Bölme örnekleri

Tam pencereden bölme

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

Yeniden düzenleme gerekmez. Bölme yapılandırmasını tanımlayabilirsiniz olarak veya çalışma zamanında Context#startActivity() çağrısı yapacak şekilde çevrimdışıyken ek parametreler'e dokunun.

<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 şekilde her iki etkinlik de oluşturulup aynı anda sunulduğunda elde edilir. Ancak içerik, bölmenin ikincil kapsayıcısı için, kullanıcı ilk işlemden sonra birincil kapsayıcıdaki etkinlik (örneğin, kullanıcı bir öğe seçer ) kullanabilirsiniz. Yer tutucu etkinlik, içerik eklenene kadar boşluğu doldurabilir bölmenin ikincil kapsayıcısında gösterilebilir (bkz. Yer tutucular bölümüne bakın).

Şekil 16. İki etkinlik aynı anda açılarak oluşturulan bölme. Bir etkinlik yer tutucudur.

Yer tutucu içeren bir 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 bir intent aldığında, hedef etkinlik etkinlik bölümünün ikincil bölümü Örneğin, bir ayrıntıyı gösterme isteği listedeki bir öğeyle ilgili bilgiler içeren bir ekran. Küçük ekranlarda ayrıntılar tam görev penceresinde, büyük ekranlarda ise listenin yanında gösterilir.

Şekil 17. Küçük ekranda tek başına, büyük ekranda ise liste etkinliğiyle birlikte gösterilen derin bağlantı ayrıntısı etkinliği.

Başlatma isteği, ana etkinliğe ve hedef ayrıntısına etkinlik bölünmüş bir şekilde başlatılmalıdır. Sistem, mevcut ekran genişliğine göre doğru sunumu (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 arka gezinme yığınında kullanabileceği tek etkinlik olabilir. Ayrıntı etkinliğini kapatıp yalnızca ana etkinliği bırakmak isteyebilirsiniz:

Liste etkinliği ile ayrıntı etkinliğini yan yana gösteren büyük ekran.
          Geri gezinme, ayrıntı etkinliği reddedilemedi ve listeden çıkılamadı
          bir etkinliktir.

Yalnızca ayrıntı etkinliği içeren küçük ekran. Geri navigasyon işlemi tamamlanamadı
          ayrıntı etkinliğini kapat ve liste etkinliğini göster.

Bunun yerine, finishPrimaryWithSecondary özelliği:

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

Yapılandırma özellikleri bölümüne bakın.

Bölünmüş kapsayıcılarda birden fazla etkinlik

Birden fazla etkinliği bölünmüş bir kapsayıcıda yığmak, kullanıcıların ayrıntılı bilgilere ve içerik. Örneğin, liste-ayrıntı bölmelerinde kullanıcının bir alt ayrıntı bölümüne gitmesi ancak birincil etkinliği yerinde tutması gerekebilir:

Şekil 18. Etkinlik, ekranın ikincil bölmesinde açıldı görev penceresi.

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 üzerine yerleştirilir ve gizlenir:

Kullanıcı, daha sonra geri dönüp önceki ayrıntı düzeyine geri dönebilir. aşağıdaki adımları izleyin:

Şekil 19. Etkinlik, grubun en üstünden kaldırıldı.

Etkinlikler aynı ikincil kapsayıcıdaki bir etkinlikten başlatıldığında varsayılan davranış, etkinliklerin birbirinin üzerine yığılmasıdır. Aktiviteler etkin bir bölümdeki birincil kapsayıcıdan başlatılan lansmanda da en üstünde yer alan ikincil bir kapsayıcı görevi görür.

Yeni bir görevdeki etkinlikler

Bölünmüş görev penceresindeki etkinlikler yeni bir görevde etkinlik başlattığında görev, bölmeyi içeren görevden ayrıdır ve tam olarak gösterilir penceresini kapatın. Son Görevler 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 ve ikincil etkinlik için kullanılır seçili bir hedeftir. Üst düzey gezinme menüsündeki her seçim, ikincil kapsayıcıda yeni bir etkinlik başlatmalı ve daha önce orada bulunan etkinliği veya etkinlikleri kaldırmalıdır.

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

Gezinme seçimi değiştiğinde uygulama ikincil kapsayıcıdaki etkinliği bitirmezse bölme daraltıldığında (cihaz katlandığında) geri gezinme kafa karıştırıcı olabilir. Örneğin, menüdeki birincil bölmede ve A ve B ekranları ikincil bölmede gruplandırılır. telefonu katlar, B tuşu A'nın üzerinde ve A menünün üzerindedir. Kullanıcı B'den geri geldiğinde menü yerine A görünür.

Bu gibi durumlarda A ekranı arka yığıntan kaldırılmalıdır.

Mevcut bir bölme üzerinde yeni bir kapsayıcıda yan tarafta başlatıldığında varsayılan davranış, yeni ikincil kapsayıcıları en üste koymak ve eski kapsayıcıları arka yığınta tutmak olur. Önceki bölümleri temizlemek için bölümleri yapılandırabilirsiniz. clearTop ile ikincil kapsayıcılar oluşturabilir ve yeni etkinlikleri normal şekilde başlatabilir.

<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 ve birincil (menü) yolunu kullanın etkinlik, aynı örneğe çözümlenen ancak bir durumu tetikleyen yeni amaçlar gönderir kullanıcı arayüzü güncellemesi yapın.

Birden fazla bölme

Uygulamalar, ek etkinlikler başlatarak çok düzeyli derin gezinme sağlayabilir görebilirsiniz.

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

Şekil 22. B etkinliği, yan tarafta C etkinliğini başlatır.

Arka yığın, daha önce açılmış olan tüm etkinlikleri içerir. Böylece kullanıcılar C'yi bitirdikten sonra A/B bölümüne gitmek için

Bir yığıntaki A, B ve C etkinlikleri. Etkinlikler üst üste yığılır
          yukarıdan aşağıya doğru sıralama: C, B, A.

Yeni bir bölme oluşturmak için yeni etkinliği mevcut ikincil kapsayıcıdan yana doğru başlatın. Hem A/B hem de B/C bölmelerinin yapılandırmaları tanımlama ve C etkinliğini normal bir şekilde 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ünme durumu değişikliklerine tepki verme

Bir uygulamadaki farklı etkinlikler, aynı performansı gösteren kullanıcı arayüzü öğeleri içerebilir fonksiyon; örneğin, hesabınıza ait hesap içeren bir pencereyi açan Ayarlar'da devre dışı bırakabilirsiniz.

Ş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ıdır.

Şekil 24. Etkinlik bölme işleminde yinelenen kullanıcı arayüzü öğeleri.

Etkinliklerin ne zaman bölündüğünü öğrenmek için şunları kontrol edin: SplitController.splitInfoList akışı gerçekleştirin veya bir işleyiciyi Bölünme durumundaki değişiklikler için SplitControllerCallbackAdapter. Ardından, kullanıcı arayüzünü buna göre 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);
            });
}

İş parçacıkları herhangi bir yaşam döngüsü durumunda başlatılabilir ancak genellikle kaynakları korumak için STARTED durumunda başlatılır (daha fazla bilgi için Kotlin iş parçacıklarını yaşam döngüsü bilincine sahip bileşenlerle kullanma başlıklı makaleyi inceleyin).

Geri çağırma, bir etkinlik durdurulduğunda da dahil olmak üzere yaşam döngüsü durumunun herhangi birinde yapılabilir. Dinleyiciler genellikle onStart() dilinde kayıtlı ve kayıtlı olmamalıdır onStop() içinde.

Tam pencere kalıcı penceresi

Bazı etkinlikler, belirli bir işlem (ör. giriş ekranı etkinliği, politika onayı ekranı veya hata mesajı) gerçekleştirilene kadar kullanıcıların uygulamayla etkileşim kurmasını engeller. Kalıcı etkinlikler önlenmelidir ortadan kaldırır.

Genişlet yapılandırması kullanılarak bir etkinlik her zaman görev penceresini doldurmaya zorlanabilir:

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

Etkinlikleri tamamlayın

Kullanıcılar, kenardan hızlıca kaydırarak bölmenin her iki tarafındaki etkinlikleri tamamlayabilir görebilirsiniz:

Şekil 25. B etkinliğini sonlandıran kaydırma hareketi.
'nı inceleyin.
Şekil 26. Kaydırma hareketi A etkinliğini bitirir.

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

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

Yapılandırma özellikleri

Bölünmüş çift kuralı özelliklerini belirterek, tüm işlemlerin tamamlanıp tamamlanmadığını bu bölünmenin bir tarafındaki aktiviteler diğer taraftaki aktiviteleri etkiler çözmüştük. Özellikler şunlardır:

  • window:finishPrimaryWithSecondary — Şu projede tüm etkinlikler nasıl tamamlanacak? İkincil kapsayıcı, birincil kapsayıcıdaki etkinlikleri 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: Etkinlikleri her zaman ilişkili kapsayıcıdakiler oluşturur
  • never: İlişkili kapsayıcıdaki etkinlikler hiçbir zaman sonlandırılmaz.
  • adjacent: Aşağıdaki durumlarda ilişkili kapsayıcıdaki etkinlikleri bitirin: iki kapsayıcı birbirine bitişik olarak görüntülenir. Ancak, üst üste yığılmış iki konteyner

Örnek:

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

Varsayılan yapılandırma

Bölünmüş bir kapsayıcıdaki tüm etkinlikler sona erdiğinde, kalan kapsayıcı pencerenin tamamını kaplar:

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

A ve B etkinliklerini içeren bölme. A tamamlandığında B, pencerenin tamamını kaplar.

A ve B etkinliklerini içeren bölme. B tamamlandığında A, pencerenin tamamını kaplar.

Etkinlikleri birlikte tamamlayın

Tüm etkinlikler olduğunda birincil kapsayıcıdaki etkinlikleri otomatik olarak tamamla aşağıdaki adımları uygulayın:

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

A ve B etkinliklerini içeren bölüm. Bu da başka bir projenin
          A&#39;yı tamamlar ve görev penceresini boş bırakır.

A ve B etkinliklerini içeren bölüm. B harfini bırakarak A tamamlandı
          tıklayın.

Birincil kapsayıcıdaki tüm etkinlikler sona erdiğinde ikincil kapsayıcıdaki etkinlikleri otomatik olarak sonlandırma:

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

A ve B etkinliklerini içeren bölüm. A tamamlandığında B de tamamlanır ve görev penceresi boş kalır.

A ve B etkinliklerini içeren bölme. A&#39;yı değiştirmeden B tamamlanır
          tıklayın.

İlk veya ikinci haftadaki tüm aktiviteler ikincil kapsayıcı kaplaması:

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

A ve B etkinliklerini içeren bölme. A sona ermiş olur. Bu da
          B&#39;yi tamamlar ve görev penceresini boş bırakır.

A ve B etkinliklerini içeren bölüm. Bu da başka bir projenin
          A&#39;yı tamamlar ve görev penceresini boş bırakır.

Kapsayıcılarda birden fazla etkinliği tamamlama

Birden fazla etkinlik bölünmüş bir kapsayıcıda yığılmışsa bir etkinliği tamamlama üst kısmı, etkinlikleri otomatik olarak en üstte tamamlamaz.

Örneğin, ikincil kapsayıcıda iki etkinlik varsa C, B'nin üzerindedir:

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

ve bölme yapılandırması, A ve B etkinliklerinin yapılandırmasına göre belirlenir:

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

en büyük etkinliğin tamamlanması bölünmeyi sürdürüyor.

Birincil kapsayıcıda A etkinliğiyle, içinde B ve C etkinlikleriyle böl
          B&#39;nin üzerine yığılmış C. C biter ve A ile B, etkinlik bölme işleminde kalır.

İkincil kapsayıcının alt (kök) etkinliği sonlandırılırsa üstündeki etkinlikler kaldırılmaz ve bölme korunur.

Birincil kapsayıcıda A etkinliğiyle, içinde B ve C etkinlikleriyle böl
          B&#39;nin üzerine yığılmış C. B biter ve A ile C, etkinlik bölümünde kalır.

Aktiviteleri bir arada tamamlamak için, mesela birincil etkinlikteki ikincil etkinlikler de yürütülür:

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

Birincil kapsayıcıda A etkinliğiyle, içinde B ve C etkinlikleriyle böl
          B&#39;nin üzerine yığılmış C olsun. Ayrıca,
          bitirmek için de

Bölme, birincil ve ikincil eğitimi birlikte bitirecek şekilde yapılandırıldığında:

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

Birincil kapsayıcıda A etkinliği, ikincil kapsayıcıda B ve C etkinlikleri (C, B&#39;nin üzerine yığılmış) ile bölünmüş. bitirir; A ve B, B satırlarını
          etkinlik dağılımı.

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

Birincil kapsayıcıda A etkinliğiyle, içinde B ve C etkinlikleriyle böl
          B&#39;nin üzerine yığılmış C. A tamamlanır ve B ile C de tamamlanır.

Bölme özelliklerini çalışma zamanında değiştirme

Etkin ve görünür bir bölme özelliği değiştirilemez. bölme kuralları ek etkinlik lansmanlarını ve yeni kapsayıcıları etkiler ancak farklı olması gerekir.

Etkin bölmelerin özelliklerini değiştirmek için yan etkinliği tamamlayın veya bir yapılandırmaya sahip olabilir.

Dinamik bölme özellikleri

Android 15 (API düzeyi 35) ve sonraki sürümler Jetpack WindowManager 1.4 tarafından desteklenir ve daha yüksek olması, etkinliğin yapılandırılabilirliğini sağlayan dinamik özellikler sunar. şunları içeren yerleştirme bölümleri:

  • Pane genişletme: Etkileşimli, sürüklenebilir ayırıcı, kullanıcıların bölmeleri tekrar boyutlandırabilirsiniz.
  • Etkinliği sabitleme: Kullanıcılar içeriği bir kapsayıcıya sabitleyebilir ve kapsayıcıdaki gezinmeyi diğer kapsayıcıdaki gezinmeden ayırabilir.
  • Tam ekran iletişim kutusunun karartılması: Uygulamalar, bir iletişim kutusunu görüntülerken görev penceresinin tamamının mı yoksa yalnızca iletişim kutusunu açan kapsayıcının mı karartılacağı belirtebilir.

Bölme genişletme

Bölme genişletmesi, kullanıcıların ayrılan ekran alanı miktarını ayarlamasına olanak tanır. iki etkinliği çift bölmeli biçimde sunar.

Pencere bölücünün görünümünü özelleştirmek ve bölücünün sürüklemeli aralığını ayarlamak için aşağıdakileri yapın:

  1. DividerAttributes örneği oluşturma

  2. Bölme özelliklerini özelleştirin:

    • color: Taşınabilir bölme ayırıcının rengi.

    • widthDp: Sürüklenebilir bölme ayırıcının genişliği. Şu değere ayarla: Ayırıcıyı sistem tarafından belirlemek için WIDTH_SYSTEM_DEFAULT dokunun.

    • Sürükleme aralığı: Her iki bölmenin de ekranda kaplayabildiği minimum yüzde. 0,33 ile 0,66 arasında olabilir. Sistemin sürükleme aralığını belirlemesine izin vermek için DRAG_RANGE_SYSTEM_DEFAULT olarak ayarlayın.

Kotlin

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

if (WindowSdkExtensions.getInstance().extensionVersion >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    )
}
val splitAttributes: SplitAttributes = splitAttributesBuilder.build()

Java

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

if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
    splitAttributesBuilder.setDividerAttributes(
      new DividerAttributes.DraggableDividerAttributes.Builder()
        .setColor(ContextCompat.getColor(context, R.color.divider_color))
        .setWidthDp(4)
        .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
        .build()
    );
}
SplitAttributes splitAttributes = splitAttributesBuilder.build();

Etkinlik sabitleme

Etkinlik sabitleme, kullanıcıların bölünmüş pencerelerden birini sabitlemelerini sağlar. Böylece kullanıcılar diğer pencerede gezinirken etkinlik olduğu gibi kalır. Etkinlik sabitleme, gelişmiş bir çoklu görev deneyimi sunar.

Uygulamanızda etkinlik sabitlemeyi etkinleştirmek için şunları yapın:

  1. Sabitlemek istediğiniz etkinliğin düzen dosyasına bir düğme ekleyin. örnek olarak, bir liste-ayrıntı düzeninin ayrıntı etkinliği görebilirsiniz:

    <androidx.constraintlayout.widget.ConstraintLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/detailActivity"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white"
     tools:context=".DetailActivity">
    
    <TextView
       android:id="@+id/textViewItemDetail"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="36sp"
       android:textColor="@color/obsidian"
       app:layout_constraintBottom_toTopOf="@id/pinButton"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toTopOf="parent" />
    
    <androidx.appcompat.widget.AppCompatButton
       android:id="@+id/pinButton"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/pin_this_activity"
       app:layout_constraintBottom_toBottomOf="parent"
       app:layout_constraintEnd_toEndOf="parent"
       app:layout_constraintStart_toStartOf="parent"
       app:layout_constraintTop_toBottomOf="@id/textViewItemDetail"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. Etkinliğin onCreate() yönteminde, düğme:

    Kotlin

    pinButton = findViewById(R.id.pinButton)
    pinButton.setOnClickListener {
        val splitAttributes: SplitAttributes = SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build()
    
        val pinSplitRule = SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build()
    
        SplitController.getInstance(applicationContext).pinTopActivityStack(taskId, pinSplitRule)
    }

    Java

    Button pinButton = findViewById(R.id.pinButton);
    pinButton.setOnClickListener( (view) => {
        SplitAttributes splitAttributes = new SplitAttributes.Builder()
            .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
            .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
            .build();
    
        SplitPinRule pinSplitRule = new SplitPinRule.Builder()
            .setSticky(true)
            .setDefaultSplitAttributes(splitAttributes)
            .build();
    
        SplitController.getInstance(getApplicationContext()).pinTopActivityStack(getTaskId(), pinSplitRule);
    });

Tam ekran karartma

Etkinlikler genellikle dikkati diyaloğa çekmek için ekranlarını karartır. Etkinlik yerleştirmede, birleşik bir kullanıcı arayüzü deneyimi için iletişim kutusunu açan etkinliği içeren panelin yanı sıra bölünmüş ekranın her iki paneli de karartılmalıdır.

WindowManager 1.4 ve sonraki sürümlerde bir güncelleme olduğunda uygulama penceresinin tamamı varsayılan olarak kararır. iletişim kutusu açılır (bkz. EmbeddingConfiguration.DimAreaBehavior.ON_TASK).

Yalnızca iletişim kutusunu açan etkinliğin kapsayıcısını karartmak için EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK.

Bir etkinliği bölünmüş pencereden tam pencereye çıkarma

Yan etkinlik tam penceresini görüntüleyen yeni bir yapılandırma oluşturun ve aynı örneğe çözümlenen bir niyetle etkinliği yeniden başlatın.

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

Etkinlik yerleştirme, Android 12L (API düzeyi 32) ve sonraki sürümlerde desteklenir ancak daha eski platform sürümlerini çalıştıran bazı cihazlarda da kullanılabilir. Özelliğin kullanılabilirliğini çalışma zamanında kontrol etmek için SplitController.splitSupportStatus mülkünü 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 etkinliğin üzerine başlatılır. yığın için (etkinlik dışı yerleştirme modeli) izler.

Sistemde geçersiz kılmayı önle

Android cihaz üreticileri (özgün donanım üreticileri veya OEM'ler), etkinlik yerleştirmeyi cihaz sisteminin bir işlevi olarak uygulayabilir. Sistem, çok etkinli uygulamalar için bölme kurallarını belirtir ve uygulamaların pencereleme davranışını geçersiz kılar. Sistem geçersiz kılma işlemi, çok etkinli uygulamaları sistem tarafından tanımlanan etkinlik yerleştirme moduna zorlar.

Sistem etkinliği yerleştirme, çoklu bölme üzerinden uygulama sunumunu iyileştirebilir list-detail gibi düzenlerde değişiklik yapmanıza gerek yoktur. Ancak sistemin etkinlik yerleştirme işlemi de yanlış uygulama düzenlerine, hatalara veya uygulama tarafından uygulanan yerleşik etkinlik ile çakışıyor.

Uygulamanız, sistem etkinliği yerleştirilmesini engelleyebilir veya buna izin verebilir. Bunun için mülkü içerebilir. Ö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'da WindowProperties tanımlanır. nesnesini tanımlayın. Uygulamanızda etkinlik yerleştirme kullanılıyorsa değeri false olarak ayarlayın. sisteme etkinlik yerleştirme uygulamasını uygulamasını engellemek istiyorsanız hakkında bilgi edindiniz. Sistemin uygulanmasına izin vermek için değeri true olarak ayarlayın. sistem tarafından tanımlanmış etkinlik yerleştirmesini gösterir.

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

  • Yalnızca kökün sahibi olarak tanımlanan görevin ana makine uygulaması diğer aktiviteleri organize edebilir ve göreve yerleştirebilir. Yerleştirme ve bölme işlemlerini destekleyen etkinlikler farklı bir uygulamaya ait bir görevde çalıştırılırsa bu etkinliklerde yerleştirme ve bölme işlemleri çalışmaz.
  • Etkinlikler yalnızca tek bir görev içinde düzenlenebilir. Etkinlik başlatma her zaman yeni bir genişletilmiş pencereye yerleştirir. bölmeniz gerekir.
  • Yalnızca aynı süreçte yer alan etkinlikler düzenlenebilir ve bölünebilir. İlgili içeriği oluşturmak için kullanılan SplitInfo geri çağırma yalnızca aynı bilgi sahibi olmadığından, farklı sektörlerdeki aktiviteler hakkında bilgi daha fazla bilgi edineceksiniz.
  • Her çift veya tekil etkinlik kuralı, yalnızca şu etkinlik kapsamındaki etkinlik başlatmalarına uygulanır: ne olduğunu öğreneceğiz. Şu anda mevcut bölümleri veya görsel özelliklerini güncelleyebilirsiniz.
  • Bölünmüş çift filtre yapılandırması, etkinlikler tamamen başlatılırken kullanılan intent'lerle eşleşmelidir. Eşleşme, yeni bir anahtar kelimenin Bu etkinlik, başvuru sürecinde başladığından ne haberi olmayabilir? kullanılırken daha sonra çözümlenen bileşen adları gizli niyettir. Lansman sırasında bir bileşen adı bilinmiyorsa, bunun yerine joker karakter ("*/*") kullanılabilir ve filtreleme, amaç işlemine göre işlem yaparsınız.
  • Şu anda, etkinlikleri kapsayıcılar arasında veya oluşturulduktan sonra bölmelere ve bölmelerden taşımak mümkün değildir. Bölmeler yalnızca Eşleşen kurallara sahip yeni etkinlikler başlatıldığında WindowManager kitaplığı, ve bölmeler, bölünmüş bir kapsayıcıdaki son etkinlik gerçekleştirildiğinde yok edilir. tamamlandı.
  • Yapılandırma değiştiğinde etkinlikler yeniden başlatılabilir. Böylece, oluşturulduğunda veya kaldırıldığında ve etkinlik sınırları değiştiğinde etkinlik örneğinin tamamen yok edilmesi ve oluşturabilirsiniz. Sonuç olarak, uygulama geliştiriciler aşağıdaki gibi konularda dikkatli olmalıdır: yaşam döngüsü geri çağırma yoluyla yeni etkinlikler başlatmak mümkün.
  • Cihazlar, etkinlik yerleştirmeyi desteklemek için pencere uzantıları arayüzünü içermelidir. Android 12L (API düzeyi) çalıştıran hemen hemen tüm büyük ekranlı cihazlar 32) veya sonraki sürümler arayüzü içerir. Ancak birden fazla etkinlik çalıştıramayan bazı büyük ekranlı cihazlarda pencere uzantıları arayüzü bulunmaz. Büyük ekranlı bir cihazda çoklu pencere desteklenmiyorsa modunda, etkinlik yerleştirmeyi desteklemeyebilir.

Ek kaynaklar