Etkinlik yerleştirme, bir uygulamanın görev penceresini iki etkinlik veya aynı etkinliğin iki örneği arasında bölerek büyük ekranlı cihazlardaki uygulamaları optimize eder.
Uygulamanız birden fazla etkinlikten oluşuyorsa etkinlik yerleştirme, tabletlerde, katlanabilir cihazlarda ve ChromeOS cihazlarda gelişmiş bir kullanıcı deneyimi sunmanızı sağlar.
Etkinlik yerleştirme için kod yeniden düzenleme gerekmez. Uygulamanızın etkinliklerini nasıl göstereceğini (yan yana veya üst üste) bir XML yapılandırma dosyası oluşturarak ya da Jetpack WindowManager API çağrıları yaparak belirleyebilirsiniz.
Küçük ekranlar için destek otomatik olarak sağlanır. Uygulamanız küçük ekranlı bir cihazda çalışırken etkinlikler üst üste yerleştirilir. Büyük ekranlarda etkinlikler yan yana gösterilir. Sistem, oluşturduğunuz yapılandırmaya göre sunuyu belirler. Dallanma mantığı gerekmez.
Etkinlik yerleştirme, cihaz yönlendirmesindeki değişikliklere uyum sağlar ve katlanabilir cihazlarda sorunsuz bir şekilde çalışır. Cihaz katlandıkça ve açıldıkça etkinlikleri üst üste yerleştirir ve kaldırır.
Etkinlik yerleştirme, Android 12L (API düzeyi 32) ve sonraki sürümleri çalıştıran çoğu büyük ekranlı cihazda desteklenir.
Bölünmüş görev penceresi
Etkinlik yerleştirme, uygulama görev penceresini birincil ve ikincil olmak üzere iki kapsayıcıya böler. Kapsayıcılar, ana etkinlikten veya kapsayıcılarda bulunan diğer etkinliklerden başlatılan etkinlikleri barındırır.
Etkinlikler başlatıldıkça ikincil kapsayıcıda üst üste yerleştirilir. İkincil kapsayıcı, küçük ekranlarda birincil kapsayıcının üstüne yerleştirilir. Bu nedenle, etkinliklerin üst üste yerleştirilmesi ve geri gezinme, uygulamanızda zaten yerleşik olan etkinliklerin sırasıyla tutarlıdır.
Etkinlik yerleştirme, etkinlikleri çeşitli şekillerde görüntülemenizi sağlar. Uygulamanız, iki etkinliği aynı anda yan yana veya üst üste başlatarak görev penceresini bölebilir:
Tüm görev penceresini kaplayan bir etkinlik, yanına yeni bir etkinlik başlatılarak bölünmüş görünüm oluşturabilir:
Zaten bölünmüş durumda olan ve bir görev penceresini paylaşan etkinlikler, diğer etkinlikleri aşağıdaki şekillerde başlatabilir:
Başka bir etkinliğin üst tarafında:
4.şekil A etkinliği, B etkinliğinin yanında C etkinliğini başlatır. Yana doğru kaydırın ve önceki birincil etkinliği gizleyerek bölünmeyi yana doğru kaydırın:
5.şekil B etkinliği, C etkinliğini yana doğru başlatır ve bölünmeyi yana doğru kaydırır. Üstte yerinde bir etkinlik başlatın. Yani aynı etkinlik yığınında:
Şekil 6. B etkinliği, C etkinliğini ek amaç işaretleri olmadan başlatır. Aynı görevde tam pencere etkinliği başlatma:
7.şekil A etkinliği veya B etkinliği, görev penceresini dolduran C etkinliğini başlatır.
Geri gezinme
Farklı uygulama türleri, etkinlikler arasındaki bağımlılıklara veya kullanıcıların geri etkinliğini nasıl tetiklediğine bağlı olarak bölünmüş görev penceresi durumunda farklı geri gezinme kurallarına sahip olabilir. Örneğin:
- Birlikte gitme: Etkinlikler ilişkiliyse ve biri diğeri olmadan gösterilmemeliyse geri gitme işlemi her ikisini de tamamlayacak şekilde yapılandırılabilir.
- Tek başına ilerleme: Etkinlikler tamamen bağımsızsa bir etkinlikte geri gitme işlemi, görev penceresindeki başka bir etkinliğin durumunu etkilemez.
Düğme navigasyonu kullanılırken geri etkinliği, son odaklanılan etkinliğe gönderilir.
Harekete dayalı gezinme için:
Android 14 (API düzeyi 34) ve önceki sürümler: Geri etkinliği, hareketin gerçekleştiği etkinliğe gönderilir. Kullanıcılar ekranın sol tarafından kaydırdığında, bölünmüş pencerenin sol bölmesindeki etkinliğe geri gitme etkinliği gönderilir. Kullanıcılar ekranın sağ tarafından kaydırdığında geri etkinliği sağdaki bölmedeki etkinliğe gönderilir.
Android 15 (API düzeyi 35) ve sonraki sürümler
Aynı uygulamadan gelen birden fazla etkinlikle uğraşı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 (overlay) yer aldığı senaryolarda geri etkinliği, odaklanılan son etkinliğe yönlendirilir. Bu, düğme gezinme davranışıyla uyumludur.
Çok panelli düzen
Jetpack WindowManager, Android 12L (API düzeyi 32) veya sonraki sürümlerin yüklü olduğu büyük ekranlı cihazlarda ve önceki platform sürümlerinin yüklü olduğu bazı cihazlarda çok panelli etkinlik yerleştirme düzeni oluşturmanıza olanak tanır. Parçalar veya görünüm tabanlı düzenler yerine birden fazla etkinliğe dayalı mevcut uygulamalar (ör. SlidingPaneLayout), kaynak kodu yeniden düzenlemeden daha iyi bir büyük ekran kullanıcı deneyimi sunabilir.
Buna yaygın bir örnek, liste-ayrıntı bölünmesidir. Yüksek kaliteli bir sunum sağlamak için sistem, liste etkinliğini başlatır ve ardından uygulama, ayrıntı etkinliğini hemen başlatır. Geçiş sistemi, her iki etkinlik de çizilene kadar bekler ve ardından bunları birlikte gösterir. Kullanıcı için iki etkinlik tek bir etkinlik olarak başlatılır.
Bölünmüş özellikler
Görevin penceresinin bölünmüş kapsayıcılar arasında nasıl orantılandığını ve kapsayıcıların birbirlerine göre nasıl düzenlendiğini belirleyebilirsiniz.
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ıkta (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. Bu değerler şunları içerir:ltr: Soldan sağartl: Sağdan solalocale: Yerel ayarındanltrveyartlbelirlenir.
Örnekler için XML yapılandırması bölümüne bakın.
WindowManager API'leri kullanılarak oluşturulan kurallar için SplitAttributes
nesnesini SplitAttributes.Builder ile oluşturun ve aşağıdaki oluşturucu yöntemlerini çağırın:
setSplitType(): Bölünmüş kapsayıcıların oranlarını ayarlar.SplitAttributes.SplitType.ratio()yöntemi de dahil olmak üzere geçerli argümanlar içinSplitAttributes.SplitTypebölümüne bakın.setLayoutDirection(): Kapsayıcıların düzenini ayarlar. Olası değerler içinSplitAttributes.LayoutDirectionbölümüne bakın.
Örnekler için WindowManager API bölümüne bakın.
Bölünmüş yön
Ekranın boyutları ve en-boy oranı, etkinlik yerleştirme bölümlerindeki etkinliklerin konumunu belirler. Geniş yatay ekranlarda etkinlikler yan yana, uzun dikey ekranlarda veya katlanabilir cihazlarda masaüstü modunda ise üst üste gösterilir.
Bölme yönünü SplitController
SplitAttributes hesaplayıcıyla belirtebilirsiniz. Hesap makinesi, etkin SplitRule için SplitAttributes değerini hesaplar.
Üst kapsayıcıyı farklı cihaz durumları için farklı yönlerde bölmek üzere hesap makinesini kullanın. Örneğin:
Kotlin
if (WindowSdkExtensions.getInstance().extensionVersion >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator { params -> val parentConfiguration = params.parentConfiguration val builder = SplitAttributes.Builder() return@setSplitAttributesCalculator if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build() } else if (parentConfiguration.screenHeightDp >= 600) { // Horizontal split for tall displays. builder .setLayoutDirection(SplitAttributes.LayoutDirection.BOTTOM_TO_TOP) .build() } else { // Fallback to expand the secondary container. builder .setSplitType(SPLIT_TYPE_EXPAND) .build() } } }
Java
if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator(params -> { Configuration parentConfiguration = params.getParentConfiguration(); SplitAttributes.Builder builder = new SplitAttributes.Builder(); if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. return builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build(); } else if (parentConfiguration.screenHeightDp >= 600) { // Horizontal split for tall displays. return builder .setLayoutDirection(SplitAttributes.LayoutDirection.BOTTOM_TO_TOP) .build(); } else { // Fallback to expand the secondary container. return builder .setSplitType(SplitType.SPLIT_TYPE_EXPAND) .build(); } }); }
Katlanabilir cihazlarda, cihaz yatay durumdaysa ekranı dikey olarak bölebilir, cihaz dikey durumdaysa tek bir etkinlik görüntüleyebilir ve cihaz masaüstü duruşundaysa ekranı yatay olarak bölebilirsiniz:
Kotlin
if (WindowSdkExtensions.getInstance().extensionVersion >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator { params -> val tag = params.splitRuleTag val parentWindowMetrics = params.parentWindowMetrics val parentConfiguration = params.parentConfiguration val foldingFeatures = params.parentWindowLayoutInfo.displayFeatures.filterIsInstance<FoldingFeature>() val feature = if (foldingFeatures.size == 1) foldingFeatures[0] else null val builder = SplitAttributes.Builder() builder.setSplitType(SPLIT_TYPE_HINGE) return@setSplitAttributesCalculator if (feature?.isSeparating == true) { // Horizontal split for tabletop posture. builder .setSplitType(SPLIT_TYPE_HINGE) .setLayoutDirection( if (feature.orientation == FoldingFeature.Orientation.HORIZONTAL) { SplitAttributes.LayoutDirection.BOTTOM_TO_TOP } else { SplitAttributes.LayoutDirection.LOCALE } ) .build() } else if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build() } else { // No split for tall displays. builder .setSplitType(SPLIT_TYPE_EXPAND) .build() } } }
Java
if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 2) { SplitController.getInstance(this).setSplitAttributesCalculator(params -> { String tag = params.getSplitRuleTag(); WindowMetrics parentWindowMetrics = params.getParentWindowMetrics(); Configuration parentConfiguration = params.getParentConfiguration(); List<FoldingFeature> foldingFeatures = params.getParentWindowLayoutInfo().getDisplayFeatures().stream().filter( item -> item instanceof FoldingFeature) .map(item -> (FoldingFeature) item) .collect(Collectors.toList()); FoldingFeature feature = foldingFeatures.size() == 1 ? foldingFeatures.get(0) : null; SplitAttributes.Builder builder = new SplitAttributes.Builder(); builder.setSplitType(SplitType.SPLIT_TYPE_HINGE); if (feature != null && feature.isSeparating()) { // Horizontal slit for tabletop posture. return builder .setSplitType(SplitType.SPLIT_TYPE_HINGE) .setLayoutDirection( feature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL ? SplitAttributes.LayoutDirection.BOTTOM_TO_TOP : SplitAttributes.LayoutDirection.LOCALE) .build(); } else if (parentConfiguration.screenWidthDp >= 840) { // Side-by-side dual-pane layout for wide displays. return builder .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE) .build(); } else { // No split for tall displays. return builder .setSplitType(SplitType.SPLIT_TYPE_EXPAND) .build(); } }); }
Yer tutucular
Yer tutucu etkinlikler, etkinlik bölümünün bir alanını kaplayan boş ikincil etkinliklerdir. Sonuç olarak, içerik barındıran başka bir etkinlikle değiştirilmesi amaçlanır. Örneğin, listeden bir öğe seçilene kadar bir liste-ayrıntı düzeninde bölünmüş bir etkinliğin ikincil tarafını bir yer tutucu etkinlik kaplayabilir. Bu noktada, seçilen liste öğesinin ayrıntı bilgilerini içeren bir etkinlik yer tutucunun yerini alır.
Varsayılan olarak sistem, yalnızca etkinlik ayrımı için yeterli alan olduğunda yer tutucuları gösterir. Ekran boyutu, bölünmeyi gösterecek kadar küçük bir genişlik veya yüksekliğe değiştiğinde yer tutucular otomatik olarak tamamlanır. Alan izin verdiğinde, sistem, yer tutucuyu yeniden başlatılmış bir durumda yeniden başlatır.
Ancak, SplitPlaceholder.Builder yönteminin SplitPlaceholderRule veya setSticky() yönteminin stickyPlaceholder özelliği varsayılan davranışı geçersiz kılabilir. Özellik veya yöntem true değerini belirttiğinde sistem, ekran iki panelli ekrandan tek panelli ekrana yeniden boyutlandırıldığında yer tutucuyu görev penceresindeki en üstteki etkinlik olarak gösterir (örnek için Bölünmüş yapılandırma bölümüne bakın).
Pencere boyutu değişiklikleri
Cihaz yapılandırması değişiklikleri, görev penceresinin genişliğini çok panelli bir düzen için yeterli olmayacak şekilde azalttığında (örneğin, büyük ekranlı katlanabilir bir cihaz tablet boyutundan telefon boyutuna katlandığında veya uygulama penceresi çok pencereli modda 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 etkinlikler yalnızca bölünme için yeterli görüntüleme 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 büyüdüğünde yer tutucu yeniden oluşturulur. (Yer tutucular bölümüne bakın.)
WindowManager, ikincil bölmedeki etkinlikleri birincil bölmedeki etkinliklerin üzerinde z-sıralamasına göre yerleştirdiği için etkinlikleri üst üste yerleştirmek mümkündür.
İkincil bölmede birden fazla etkinlik
B etkinliği, C etkinliğini ek niyet işaretleri olmadan yerinde başlatır:

Bu durumda, aynı görevdeki etkinliklerin z-sırası aşağıdaki gibi olur:

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

Küçük pencerede geri gitmek, üst üste yerleştirilmiş etkinlikler arasında gezinmenizi sağlar.
Görev penceresi yapılandırması, birden fazla bölmeyi barındırabilecek daha büyük bir boyuta geri yüklenirse etkinlikler tekrar yan yana gösterilir.
Yığılmış bölmeler
B etkinliği, C etkinliğini yana doğru başlatır ve bölünmeyi yana doğru kaydırır:

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

Daha küçük bir görev penceresinde uygulama, üstte C harfiyle tek bir etkinliğe küçülür:

Sabit dikey yön
android:screenOrientation manifest ayarı, uygulamaların etkinlikleri dikey veya yatay yönle sınırlamasına olanak tanır. Tabletler ve katlanabilir cihazlar gibi büyük ekranlı cihazlarda kullanıcı deneyimini iyileştirmek için cihaz üreticileri (OEM'ler) ekran yönü isteklerini yoksayabilir ve uygulamayı yatay ekranlarda dikey yönde, dikey ekranlarda ise yatay yönde letterbox'layabilir.
Benzer şekilde, aktivite yerleştirme etkinleştirildiğinde OEM'ler, cihazları büyük ekranlarda (genişlik ≥ 600 dp) yatay yönde sabit dikey aktiviteleri letterbox'a göre özelleştirebilir. Sabit dikey yönlü bir etkinlik ikinci bir etkinliği başlattığında cihaz, iki etkinliği iki panelli bir ekranda yan yana gösterebilir.
Uygulamanızın etkinlik yerleştirmeyi desteklediğini cihazlara bildirmek için uygulama manifest dosyanıza her zaman android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED
özelliğini ekleyin (Bölünmüş yapılandırma
bölümüne bakın). OEM'ler tarafından özelleştirilmiş cihazlar, sabit dikey yönlü etkinliklere letterbox uygulanıp uygulanmayacağını belirleyebilir.
Bölme yapılandırması
Bölme kuralları, etkinlik bölümlerini yapılandırır. Bölme kurallarını bir XML yapılandırma dosyasında veya Jetpack WindowManager API çağrıları yaparak tanımlarsınız.
Her iki durumda da uygulamanızın WindowManager kitaplığına erişmesi ve sisteme, uygulamanın etkinlik yerleştirme özelliğini uyguladığını bildirmesi gerekir.
Aşağıdakileri yapın:
Uygulamanızın modül düzeyindeki
build.gradledosyasına en yeni 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.
Sisteme, uygulamanızda etkinlik yerleştirmenin uygulandığını bildirin.
android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLEDözelliğini uygulama manifest dosyasının <application> öğesine ekleyin ve değeri doğru 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 olarak ayarlanmadığı sürece etkinlik yerleştirme bölmeleri devre dışı bırakılır.
Ayrıca, cihaz üreticileri 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 panelli düzene geçiş için etkinliği yönlendirmek üzere yatay ekranlarda yalnızca dikey etkinliğe letterbox uygulayabilir (bkz. Sabit dikey yönlendirme).
XML yapılandırması
Etkinlik yerleştirmenin XML tabanlı bir uygulamasını oluşturmak için aşağıdaki adımları tamamlayın:
Aşağıdaki işlemleri yapan bir XML kaynak dosyası oluşturun:
- Bölünmüş bir öğeyi paylaşan etkinlikleri tanımlar.
- Bölünme seçeneklerini yapılandırır.
- İçerik kullanılamadığında bölünmenin ikincil kapsayıcısı için yer tutucu oluşturur.
- Hiçbir zaman bölme işlemine dahil edilmemesi 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>Başlatıcı oluşturun.
WindowManager
RuleControllerbileşeni, XML yapılandırma dosyasını ayrıştırır ve kuralları sistemde kullanılabilir hale getirir. Jetpack Startup kitaplığıInitializer, uygulama başlatıldığında XML dosyasınıRuleControlleriçin kullanılabilir hale getirir. Böylece, etkinlikler başladığında kurallar geçerli olur.Başlatıcı oluşturmak için aşağıdakileri yapın:
Modül düzeyindeki
build.gradledosyanıza en yeni Jetpack Startup kitaplığı bağımlılığını ekleyin. Örneğin:implementation 'androidx.startup:startup-runtime:1.1.1'Initializerarayüzünü uygulayan bir sınıf oluşturun.Başlatıcı,
RuleControlleryöntemine XML yapılandırma dosyasının kimliğini (main_split_config.xml) ileterek bölme kurallarınıRuleController.parseRules()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(); } }
Kural tanımları için bir içerik sağlayıcı oluşturun.
Uygulama manifest dosyanıza
androidx.startup.InitializationProvideröğesini<provider>olarak ekleyin.RuleControllerbaşlatıcınızınSplitInitializeruygulanmasına referans verin:<!-- 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ınonCreate()yöntemi çağrılmadan önce keşfedilir ve başlatılır.SplitInitializerSonuç olarak, uygulamanın ana etkinliği başladığında bölme kuralları geçerli olur.
WindowManager API
Etkinlik yerleştirmeyi birkaç API çağrısıyla programatik olarak uygulayabilirsiniz. Kuralların herhangi bir etkinlik başlatılmadan önce geçerli olmasını sağlamak için Application alt sınıfının onCreate() yönteminde çağrı yapın.
Etkinlik bölümü oluşturmak için aşağıdakileri yapın:
Bölme kuralı oluşturma:
Bölünmeyi paylaşan etkinlikleri tanımlayan bir
SplitPairFilteroluş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 );
Filtreyi bir filtre grubuna ekleme:
```Kotlin
val filterSet = setOf(splitPairFilter)
Java
Set<SplitPairFilter> filterSet = new HashSet<>(); filterSet.add(splitPairFilter);
Bölünme 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
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 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 birbirlerine göre nasıl düzenleneceğini belirtir. Birincil kapsayıcı önce gelir.
SplitPairRuleoluş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.Builderkuralı oluşturur ve yapılandırır:filterSet: Bölünmüş bir öğeyi paylaşan etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen bölünmüş çift filtreleri içerir.setDefaultSplitAttributes(): Düzen özelliklerini kurala uygular.setMinWidthDp(): Bölünmeyi sağlayan minimum görüntüleme genişliğini (yoğunluktan bağımsız piksel cinsinden) ayarlar.setMinSmallestWidthDp(): Cihaz yönünden bağımsız olarak bölünmeyi etkinleştirmek için iki ekran boyutundan küçüğünün sahip olması gereken minimum değeri (dp cinsinden) ayarlar.setMaxAspectRatioInPortrait(): Etkinlik bölümlerinin gösterildiği dikey yöndeki maksimum görüntüleme en-boy oranını (yükseklik:genişlik) ayarlar. Dikey bir ekranın en boy oranı maksimum en boy oranını aşıyorsa 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 etkinliklerin görev penceresinin tamamını kaplamasına neden olur. AyrıcaSPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULTvesetMaxAspectRatioInLandscape()politikalarını da inceleyin. Yatay için varsayılan değerALWAYS_ALLOW'dir.setFinishPrimaryWithSecondary(): İkincil kapsayıcıdaki tüm etkinliklerin tamamlanmasının birincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini ayarlar.NEVER, ikincil kapsayıcıdaki tüm etkinlikler tamamlandığında sistemin birincil etkinlikleri tamamlamaması gerektiğini gösterir (bkz. Etkinlikleri tamamlama).setFinishSecondaryWithPrimary(): Birincil kapsayıcıdaki tüm etkinliklerin tamamlanmasının ikincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini ayarlar.ALWAYS, birincil kapsayıcıdaki tüm etkinlikler tamamlandığında sistemin ikincil kapsayıcıdaki etkinlikleri her zaman tamamlaması gerektiğini gösterir (bkz. Etkinlikleri tamamlama).setClearTop(): Container'da yeni bir etkinlik başlatıldığında ikincil container'daki tüm etkinliklerin tamamlanıp tamamlanmadığını belirtir.falsedeğeri, yeni etkinliklerin ikincil kapsayıcıda bulunan etkinliklerin üzerine yığıldığını belirtir.
WindowManager'ın tekil örneğini alın
RuleControllerve kuralı ekleyin:Kotlin
val ruleController = RuleController.getInstance(this) ruleController.addRule(splitPairRule)
Java
RuleController ruleController = RuleController.getInstance(this); ruleController.addRule(splitPairRule);
İçerik kullanılamadığında ikincil kapsayıcı için yer tutucu oluşturun:
Yer tutucunun görev penceresi bölümünü paylaştığı etkinliği tanımlayan bir
ActivityFilteroluşturun:Kotlin
val placeholderActivityFilter = ActivityFilter( ComponentName(this, ListActivity::class.java), null )
Java
ActivityFilter placeholderActivityFilter = new ActivityFilter( new ComponentName(this, ListActivity.class), null );
Filtreyi bir filtre grubuna ekleme:
Kotlin
val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
Java
Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>(); placeholderActivityFilterSet.add(placeholderActivityFilter);
SplitPlaceholderRuleoluşturma: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(this, PlaceholderActivity.class) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build();
SplitPlaceholderRule.Builderkuralı oluşturur ve yapılandırır:placeholderActivityFilterSet: Yer tutucu etkinliğin ilişkilendirildiği etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen etkinlik filtrelerini içerir.Intent: Yer tutucu etkinliğin 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ünden bağımsız olarak bölünmeye izin vermek için iki ekran boyutundan küçüğünün sahip olması gereken minimum değeri (dp cinsinden) ayarlar.setMaxAspectRatioInPortrait(): Etkinlik bölümlerinin gösterildiği dikey yöndeki maksimum ekran en-boy oranını (yükseklik:genişlik) ayarlar. Not: Varsayılan değer 1,4'tür.Bu değer, çoğu tablette görev penceresinin dikey yönde etkinliklerle doldurulmasına neden olur. AyrıcaSPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULTvesetMaxAspectRatioInLandscape()politikalarını da inceleyin. Yatay için varsayılan değerALWAYS_ALLOW'dir.setFinishPrimaryWithPlaceholder(): Yer tutucu etkinliğin tamamlanmasının birincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini ayarlar. ALWAYS, yer tutucu tamamlandığında sistemin her zaman birincil kapsayıcıdaki etkinlikleri tamamlaması gerektiğini gösterir (bkz. Etkinlikleri tamamlama).setSticky(): Yer tutucu, yeterli minimum genişliğe sahip bir bölmede ilk kez göründükten sonra küçük ekranlarda etkinlik yığınında yer tutucu etkinliğinin en üstte görünüp görünmeyeceğini belirler.
Kuralı WindowManager'a ekleyin
RuleController:Kotlin
ruleController.addRule(splitPlaceholderRule)
Java
ruleController.addRule(splitPlaceholderRule);
Hiçbir zaman bölme işlemine dahil edilmemesi gereken etkinlikleri belirtin:
Her zaman görev görüntüleme alanının tamamını kaplaması gereken bir etkinliği tanımlayan bir
ActivityFilteroluşturun:Kotlin
val expandedActivityFilter = ActivityFilter( ComponentName(this, ExpandedActivity::class.java), null )
Java
ActivityFilter expandedActivityFilter = new ActivityFilter( new ComponentName(this, ExpandedActivity.class), null );
Filtreyi bir filtre grubuna ekleme:
Kotlin
val expandedActivityFilterSet = setOf(expandedActivityFilter)
Java
Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>(); expandedActivityFilterSet.add(expandedActivityFilter);
ActivityRuleoluşturma:Kotlin
val activityRule = ActivityRule.Builder(expandedActivityFilterSet) .setAlwaysExpand(true) .build()
Java
ActivityRule activityRule = new ActivityRule.Builder( expandedActivityFilterSet ).setAlwaysExpand(true) .build();
ActivityRule.Builderkuralı oluşturur ve yapılandırır:expandedActivityFilterSet: Bölünmelerden hariç tutmak istediğiniz etkinlikleri belirleyerek kuralın ne zaman uygulanacağını belirleyen etkinlik filtrelerini içerir.setAlwaysExpand(): Etkinliğin görev penceresinin tamamını doldurup doldurmayacağını belirtir.
Kuralı WindowManager'a ekleyin
RuleController: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 olarak entegre edilmesini sağlar. Sistem, ana uygulamanın bir etkinliğini ve başka bir uygulamadan yerleştirilmiş bir etkinliği ekranda yan yana veya tek uygulamalı etkinlik yerleştirmede olduğu gibi üst ve alt kısımlarda gösterir.
Örneğin, Ayarlar uygulaması, WallpaperPicker uygulamasındaki duvar kağıdı seçici etkinliğini yerleştirebilir:
Güven modeli
Diğer uygulamalardan 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 tuzağı veya diğer kullanıcı arayüzü saldırıları oluşturmak için bu özelliği kullanabilir.
Uygulamalar arası etkinlik yerleştirmenin kötüye kullanılmasını önlemek için Android, uygulamaların 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 etkinliklerin sunumunu yerleştirmesine ve tam olarak kontrol etmesine izin vermek için uygulamanızın manifest dosyasındaki <activity> veya <application> öğelerinin android:knownActivityEmbeddingCerts özelliğinde ana makine uygulamasını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 dizi dize:
<activity
android:name=".MyEmbeddableActivity"
android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
... />
Aşağıdaki gibi bir kaynağa referans verilir:
<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 sertifikası özeti alabilir. Sertifika özeti, ayıran iki nokta üst üste işaretleri olmadan SHA-256 parmak izidir. Daha fazla bilgi için İmzalama raporu çalıştırma ve İstemcinizin kimliğini doğrulama başlıklı makaleleri inceleyin.
Güvenilmeyen ana makineler
Herhangi bir uygulamanın, uygulamanızın etkinliklerini yerleştirmesine ve sunumları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"
... />
Özniteliğin varsayılan değeri false'tur. Bu değer, 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. Düzenleyen, etkinliğinizi yerleştirdikten sonra kimliğini doğrularsa gerçek içeriği gösterebilirsiniz. Aksi takdirde, kullanıcıya işlemin gerçekleştirilmesine 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(context).isActivityEmbedded(activity); }
Minimum boyut kısıtlaması
Android sistemi, uygulama manifest dosyasındaki <layout> öğesinde belirtilen minimum yüksekliği ve genişliği yerleştirilmiş etkinliklere uygular. Bir uygulama minimum yükseklik ve genişlik belirtmezse sistemin varsayılan değerleri (sw220dp) geçerli olur.
Ana makine, yerleştirilmiş kapsayıcıyı minimum boyuttan daha küçük bir boyuta yeniden boyutlandırmaya çalışırsa yerleştirilmiş kapsayıcı, görev sınırlarının tamamını kaplayacak şekilde genişler.
<activity-alias>
Güvenilen veya güvenilmeyen etkinlik yerleştirmenin
<activity-alias> öğesiyle çalışması için android:knownActivityEmbeddingCerts veya
android:allowUntrustedActivityEmbedding, hedef etkinliğe takma ad yerine uygulanmalıdır. Sistem sunucusundaki güvenliği doğrulayan politika, hedefte ayarlanan işaretlere dayanır, diğer adlara değil.
Ana makine uygulaması
Ana makine uygulamaları, uygulamalar arası etkinlik yerleştirmeyi tek uygulamalı etkinlik yerleştirmeyle aynı şekilde uygular. SplitPairRule ve
SplitPairFilter veya ActivityRule ve ActivityFilter nesneleri
yerleştirilmiş etkinlikleri ve görev penceresi bölümlerini 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 ana makine uygulaması, uygulamalar arası yerleştirmeyi etkinleştirmemiş bir etkinliği yerleştirmeye çalışırsa etkinlik, görev sınırlarının tamamını kaplar. Bu nedenle, hedef etkinliklerin uygulamalar arası yerleştirmeye izin verip vermediğini ana makine uygulamalarının bilmesi gerekir.
Yerleştirilmiş bir etkinlik aynı görevde yeni bir etkinlik başlatırsa ve yeni etkinlik uygulamalar arası yerleştirmeyi etkinleştirmediyse etkinlik, yerleştirilmiş kapsayıcıdaki etkinliğin üzerine yerleştirilmek yerine görev sınırlarının tamamını kaplar.
Bir ana uygulama, etkinlikler aynı görevde başlatıldığı sürece kendi etkinliklerini kısıtlama olmadan yerleştirebilir.
Bölünmüş örnekler
Tam pencereden bölme
Yeniden düzenleme gerekmez. Bölünmenin yapılandırmasını statik olarak veya çalışma zamanında tanımlayabilir, ardından Context#startActivity() işlevini ek parametre olmadan çağırabilirsiniz.
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Varsayılan olarak bölünür
Bir uygulamanın açılış sayfası büyük ekranlarda iki kapsayıcıya bölünecek şekilde tasarlandığında, her iki etkinlik de aynı anda oluşturulup sunulduğunda kullanıcı deneyimi en iyi seviyede olur. Ancak, kullanıcı birincil kapsayıcıdaki etkinlikle etkileşime girene kadar (ör. kullanıcı bir gezinme menüsünden bir öğe seçene kadar) içerik, bölünmenin ikincil kapsayıcısında kullanılamayabilir. İçerik, bölünmüş ekranın ikincil kapsayıcısında gösterilene kadar yer tutucu etkinlikler bu boşluğu doldurabilir (bkz. Yer tutucular bölümü).
Yer tutucu içeren bir bölüm oluşturmak için yer tutucu oluşturun ve bunu birincil etkinlikle ilişkilendirin:
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity">
<ActivityFilter
window:activityName=".MainActivity"/>
</SplitPlaceholderRule>
Derin bağlantı bölme
Bir uygulama amaç aldığında hedef etkinlik, etkinlik bölünmesinin ikincil kısmı olarak gösterilebilir. Örneğin, listedeki bir öğe hakkında bilgi içeren ayrıntı ekranını gösterme isteği. Küçük ekranlarda ayrıntılar tam görev penceresinde, daha büyük cihazlarda ise listenin yanında gösterilir.
Başlatma isteği ana etkinliğe yönlendirilmeli ve hedef ayrıntı etkinliği bölünmüş olarak başlatılmalıdır. Sistem, kullanılabilir ekran genişliğine göre doğru sunumu (üst üste veya yan yana) otomatik olarak seçer.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) RuleController.getInstance(this) .addRule(SplitPairRule.Builder(filterSet).build()) startActivity(Intent(this, DetailActivity::class.java)) }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); RuleController.getInstance(this) .addRule(new SplitPairRule.Builder(filterSet).build()); startActivity(new Intent(this, DetailActivity.class)); }
Derin bağlantı hedefi, geri gezinme yığınında kullanıcının erişebileceği tek etkinlik olabilir. Bu nedenle, ayrıntı etkinliğini kapatıp yalnızca ana etkinliği bırakmaktan kaçınmak isteyebilirsiniz:


Bunun yerine, finishPrimaryWithSecondary özelliğini kullanarak her iki etkinliği aynı anda tamamlayabilirsiniz:
<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
Bölünmüş bir kapsayıcıda birden fazla etkinliği üst üste yerleştirmek, kullanıcıların ayrıntılı içeriğe erişmesini sağlar. Örneğin, liste-ayrıntı bölmesiyle kullanıcı, bir alt ayrıntı bölümüne gitmesi gerekebilir ancak birincil etkinliği yerinde tutabilir:
Kotlin
class DetailActivity : AppCompatActivity() { fun onOpenSubdetail() { startActivity(Intent(this, SubdetailActivity::class.java)) } }
Java
public class DetailActivity extends AppCompatActivity { void onOpenSubdetail() { startActivity(new Intent(this, SubdetailActivity.class)); } }
Alt ayrıntı etkinliği, ayrıntı etkinliğinin üzerine yerleştirilerek onu gizler:

Kullanıcı daha sonra yığın içinde geri giderek önceki ayrıntı düzeyine dönebilir:
Etkinlikler aynı ikincil kapsayıcıdaki bir etkinlikten başlatıldığında, etkinlikleri üst üste yerleştirmek varsayılan davranıştır. Etkin bir bölme içindeki birincil kapsayıcıdan başlatılan etkinlikler de etkinlik yığınının en üstündeki ikincil kapsayıcıda yer alır.
Yeni görevdeki etkinlikler
Bölünmüş görev penceresindeki etkinlikler yeni bir görevde etkinlikleri başlattığında, yeni görev bölünmeyi içeren görevden ayrıdır ve tam pencere olarak görüntülenir. Son Kullanılanlar ekranında iki görev gösterilir: bölünmüş ekrandaki görev ve yeni görev.
Etkinlik değiştirme
Etkinlikler ikincil kapsayıcı yığınında değiştirilebilir. Örneğin, birincil etkinlik üst düzey gezinme için, ikincil etkinlik ise seçilen bir hedef için kullanıldığında. Üst düzey gezinmedeki 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.
Uygulama, gezinme seçimi değiştiğinde etkinliği ikincil kapsayıcıda tamamlamazsa bölünme daraltıldığında (cihaz katlandığında) geri gezinme kafa karıştırıcı olabilir. Örneğin, birincil bölmede bir menünüz ve ikincil bölmede A ve B ekranlarınız varsa kullanıcı telefonu katladığında B, A'nın üzerinde, A ise menünün üzerinde olur. Kullanıcı B'den geri döndüğünde menü yerine A görünür.
Bu gibi durumlarda A ekranı, geri yığında kaldırılmalıdır.

Mevcut bir bölme üzerinde yeni bir kapsayıcıda yana doğru başlatıldığında varsayılan davranış, yeni ikincil kapsayıcıları en üste yerleştirmek ve eski kapsayıcıları 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
inner class MenuActivity : AppCompatActivity() { fun onMenuItemSelected(selectedMenuItem: Int) { startActivity(Intent(this, classForItem(selectedMenuItem))) } }
Java
public class MenuActivity extends AppCompatActivity{ 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ünme
Uygulamalar, yan tarafta ek etkinlikler başlatarak çok düzeyli derin gezinme sağlayabilir.
İkincil bir kapsayıcıdaki etkinlik, yan tarafta yeni bir etkinlik başlattığında mevcut bölünmenin üzerinde yeni bir bölünme oluşturulur.
Geri yığında daha önce açılan tüm etkinlikler yer alır. Bu nedenle, kullanıcılar C'yi tamamladıktan sonra A/B bölünmesine gidebilir.

Yeni bir bölme oluşturmak için yeni etkinliği mevcut ikincil kapsayıcının yan tarafında başlatın. Hem A/B hem de B/C bölümleri için yapılandırmaları bildirin ve C etkinliğini B'den normal şekilde başlatın:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
<SplitPairFilter
window:primaryActivityName=".B"
window:secondaryActivityName=".C"/>
</SplitPairRule>
Kotlin
class B : AppCompatActivity() { fun onOpenC() { startActivity(Intent(this, C::class.java)) } }
Java
public class B extends AppCompatActivity{ 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.
Ortak bir kullanıcı arayüzü öğesine sahip iki etkinlik bölünmüşse öğeyi her iki etkinlikte de göstermek gereksiz ve kafa karıştırıcı olabilir.
Etkinliklerin ne zaman bölünme içinde olduğunu öğrenmek için SplitController.splitInfoList akışını kontrol edin veya bölünme durumundaki değişiklikler için SplitControllerCallbackAdapter ile bir dinleyici kaydedin. 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 { 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) { super.onCreate(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); }); }
Coroutine'ler 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 coroutine'lerini kullanma konusuna bakın).
Geri çağırmalar, bir etkinlik durdurulduğunda dahil olmak üzere herhangi bir yaşam döngüsü durumunda yapılabilir. Dinleyiciler genellikle onStart() adresine kaydolmalı ve onStop() adresinden kayıtlarını silmelidir.
androidx.window:window-java
Tam pencere kalıcı penceresi
Bazı etkinlikler, belirli bir işlem yapılana kadar kullanıcıların uygulamayla etkileşimde bulunmasını engeller. Örneğin, giriş ekranı etkinliği, politika onay ekranı veya hata mesajı. Modal etkinliklerin bölünmüş ekranda görünmesi engellenmelidir.
Genişletme yapılandırması kullanılarak bir etkinliğin her zaman görev penceresini doldurması zorunlu kılınabilir:
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".FullWidthActivity"/>
</ActivityRule>
Etkinlikleri tamamlama
Kullanıcılar, ekranın kenarından kaydırarak bölünmüş ekranın her iki tarafındaki etkinlikleri tamamlayabilir:
Cihaz, hareketle gezinme yerine geri düğmesini kullanacak şekilde ayarlanmışsa giriş, odaklanılan etkinliğe (en son dokunulan veya başlatılan etkinlik) gönderilir.
Bir kapsayıcıdaki tüm etkinliklerin tamamlanmasının karşıt kapsayıcı üzerindeki etkisi, bölünme yapılandırmasına bağlıdır.
Yapılandırma özellikleri
Bölünmenin bir tarafındaki tüm etkinliklerin tamamlanmasının bölünmenin diğer tarafındaki etkinlikleri nasıl etkileyeceğini yapılandırmak için bölünmüş çift 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: Etkinlikleri her zaman ilişkili kapsayıcıda tamamlayın.never: İlişkili kapsayıcıdaki etkinlikleri hiçbir zaman tamamlamaz.adjacent: İki kapsayıcı yan yana görüntülendiğinde ilişkili kapsayıcıdaki etkinlikleri tamamlayın. İki kapsayıcı üst üste görüntülendiğinde ise tamamlamayı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ünmüş bir pencerenin bir kapsayıcısındaki tüm etkinlikler tamamlandığında kalan kapsayıcı pencerenin tamamını kaplar:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>


Etkinlikleri birlikte tamamlama
İ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>


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>


Birincil veya ikincil kapsayıcıdaki tüm etkinlikler tamamlandığında etkinlikleri birlikte bitirme:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>


Container'larda birden fazla etkinliği tamamlama
Bölünmüş bir kapsayıcıda birden fazla etkinlik üst üste yerleştirilmişse yığının en altındaki bir etkinliği tamamlamak, en üstteki etkinlikleri otomatik olarak tamamlamaz.
Örneğin, ikincil kapsayıcıda iki etkinlik varsa (B'nin üzerinde C):

ve bölünmenin yapılandırması, A ve B etkinliklerinin yapılandırmasıyla tanımlanır:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Üstteki etkinliği bitirirseniz bölünmüş ekran korunur.

İkincil kapsayıcının alt (kök) etkinliğinin tamamlanması, üstündeki etkinlikleri kaldırmaz ve bu nedenle bölünmeyi de korur.

Etkinlikleri birlikte tamamlama ile ilgili diğer kurallar da (ör. ikincil etkinliği birincil etkinlikle birlikte tamamlama) uygulanır:
<SplitPairRule
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>

Bölünme, birincil ve ikincil öğelerin birlikte tamamlanacağı şekilde yapılandırıldığında:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>



Bölünmüş özellikleri çalışma zamanında değiştirme
Etkin ve görünür bir bölünmenin özellikleri değiştirilemez. Bölme kurallarının değiştirilmesi, ek etkinlik başlatmalarını ve yeni kapsayıcıları etkiler ancak mevcut ve etkin bölmeleri etkilemez.
Etkin bölümlerin özelliklerini değiştirmek için bölümdeki yan etkinliği veya etkinlikleri tamamlayın ve yeni bir yapılandırmayla tekrar yan etkinliği başlatın.
Dinamik ayrılmış özellikler
Jetpack WindowManager 1.4 ve sonraki sürümlerin desteklediği Android 15 (API düzeyi 35) ve sonraki sürümlerde, aşağıdakiler de dahil olmak üzere etkinlik yerleştirme bölümlerinin yapılandırılabilirliğini sağlayan dinamik özellikler bulunur:
- Bölme genişletme: Etkileşimli ve sürüklenebilir bir ayırıcı, kullanıcıların bölünmüş bir sunumdaki bölmeleri yeniden boyutlandırmasına olanak tanır.
- Etkinlik yığını sabitleme: Kullanıcılar, bir kapsayıcıdaki içeriği sabitleyebilir ve kapsayıcıdaki gezinme işlemini diğer kapsayıcıdaki gezinme işleminden ayırabilir.
- İletişim kutusu tam ekran karartma: Uygulamalar, bir iletişim kutusu gösterirken görev penceresinin tamamının mı yoksa yalnızca iletişim kutusunu açan kapsayıcının mı karartılacağını belirtebilir.
Bölmeyi genişletme
Bölme genişletme, kullanıcıların iki bölmeli düzende iki etkinliğe ayrılan ekran alanını ayarlamasına olanak tanır.
Pencere ayırıcısının görünümünü özelleştirmek ve ayırıcının sürüklenebilir aralığını ayarlamak için aşağıdakileri yapın:
DividerAttributesörneği oluşturmaAyırıcı özelliklerini özelleştirme:
color: Sürüklenerek taşınabilen bölme ayırıcısının rengi.widthDp: Sürüklenerek taşınabilen bölme ayırıcısının genişliği. Sistemin ayırıcı genişliğini belirlemesine izin vermek içinWIDTH_SYSTEM_DEFAULTolarak ayarlayın.Sürükleme aralığı: Her iki bölmenin de ekranın minimum hangi yüzdesini kaplayabileceğini belirler. 0,33 ile 0,66 arasında olabilir. Sistemin sürükleme aralığını belirlemesine izin vermek için
DRAG_RANGE_SYSTEM_DEFAULTolarak 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(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(this, R.color.divider_color)) .setWidthDp(4) .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT) .build() ); } SplitAttributes _splitAttributes = splitAttributesBuilder.build();
Etkinlik yığını sabitleme
Etkinlik yığını sabitleme, kullanıcıların bölünmüş pencerelerden birini sabitlemesine olanak tanır. Böylece kullanıcılar diğer pencerede gezinirken etkinlik olduğu gibi kalır. Etkinlik yığını sabitleme, gelişmiş bir çoklu görev deneyimi sunar.
Uygulamanızda etkinlik yığını sabitlemeyi etkinleştirmek için aşağıdakileri yapın:
Sabitlemek istediğiniz etkinliğin düzen dosyasına bir düğme ekleyin. Örneğin, liste-ayrıntı düzeninin ayrıntı etkinliği:
<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>Etkinliğin
onCreate()yönteminde düğmeye bir onclick işleyici ayarlayın:Kotlin
val pinButton: Button = 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); });
İletişim kutusu tam ekran loş
Etkinlikler genellikle bir iletişim kutusuna dikkat çekmek için ekranlarını karartır. Etkinlik yerleştirme sırasında, birleşik bir kullanıcı arayüzü deneyimi için çift bölmeli ekranın her iki bölmesi de karartılmalıdır. İletişim kutusunu açan etkinliği içeren bölme karartılmamalıdır.
WindowManager 1.4 ve sonraki sürümlerde, bir iletişim kutusu açıldığında varsayılan olarak uygulamanın tamamı karartılır (EmbeddingConfiguration.DimAreaBehavior.ON_TASK bölümüne bakın).
Yalnızca iletişim kutusunu açan etkinliğin kapsayıcısını karartmak için EmbeddingConfiguration.DimAreaBehavior.ON_ACTIVITY_STACK kullanın.
Bölünmüş pencereden tam pencereye etkinlik çıkarma
Yan etkinliği tam pencere olarak görüntüleyen yeni bir yapılandırma oluşturun ve ardından etkinliği aynı örneğe çözümlenen bir amaçla yeniden başlatın.
Çalışma zamanında bölünmüş destek olup olmadığını kontrol etme
Etkinlik yerleştirme, 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. Özelliğin kullanılabilirliğini çalışma zamanında 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 üstünde başlatılır (etkinlik yerleştirme dışı modeli izleyerek).
Sistem geçersiz kılmasını önleme
Android cihazların üreticileri (özgün donanım üreticileri veya OEM'ler), etkinlik yerleştirmeyi cihaz sisteminin bir işlevi olarak uygulayabilir. Sistem, çok etkinlikli uygulamalar için bölme kurallarını belirtir ve uygulamaların pencereleme davranışını geçersiz kılar. Sistemin geçersiz kılma işlemi, çok etkinlikli uygulamaları sistem tarafından tanımlanan bir etkinlik yerleştirme moduna zorlar.
Sistem etkinliği yerleştirme, uygulamada herhangi bir değişiklik yapmadan liste-ayrıntı gibi çok panelli düzenler aracılığıyla uygulama sunumunu iyileştirebilir. Ancak sistemin etkinliği yerleştirmesi, yanlış uygulama düzenlerine, hatalara veya uygulama tarafından uygulanan etkinlik yerleştirmeyle çakışmalara da neden olabilir.
Uygulamanız, uygulama manifest dosyasında PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE ayarını yaparak 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 uygulanıyorsa veya sistemin etkinlik yerleştirme kurallarını uygulamanıza uygulamasını başka bir şekilde önlemek istiyorsanız değeri false olarak ayarlayın. Sistemin, sisteme tanımlı etkinlik yerleştirmeyi uygulamanıza uygulamasına izin vermek için değeri true olarak ayarlayın.
Sınırlamalar, kısıtlamalar ve uyarılar
- Yalnızca görevin ana uygulaması (görevdeki kök etkinliğin sahibi olarak tanımlanır) diğer etkinlikleri görevde düzenleyip yerleştirebilir. Yerleştirmeyi ve bölmeleri destekleyen etkinlikler farklı bir uygulamaya ait bir görevde çalıştırılıyorsa bu etkinliklerde yerleştirme ve bölme özellikleri kullanılamaz.
- Etkinlikler yalnızca tek bir görev içinde düzenlenebilir. Yeni bir görevde etkinlik başlatmak, etkinliği her zaman mevcut bölmelerin dışında yeni ve genişletilmiş bir pencerede açar.
- Yalnızca aynı süreçteki etkinlikler düzenlenebilir ve bölüme yerleştirilebilir. Farklı süreçlerdeki etkinlikler hakkında bilgi edinmenin bir yolu olmadığından,
SplitInfogeri çağırma işlevi yalnızca aynı sürece ait etkinlikleri bildirir. - Her çift veya tekil etkinlik kuralı yalnızca kural kaydedildikten sonra gerçekleşen etkinlik başlatmaları için geçerlidir. Mevcut bölümleri veya görsel özelliklerini güncellemek şu anda mümkün değildir.
- Bölünmüş çift filtre yapılandırması, etkinlikler tamamen başlatılırken kullanılan amaçlarla eşleşmelidir. Eşleştirme, uygulama sürecinden yeni bir etkinlik başlatıldığında gerçekleşir. Bu nedenle, örtülü amaçlar kullanılırken sistem sürecinde daha sonra çözümlenen bileşen adları hakkında bilgi sahibi olmayabilir. Bir bileşen adı lansman sırasında bilinmiyorsa bunun yerine joker karakter ("*/*") kullanılabilir ve filtreleme, amaç işlemine göre yapılabilir.
- Şu anda, etkinlikler oluşturulduktan sonra kapsayıcılar arasında veya bölümlerin içine ve dışına taşınamaz. Bölmeler yalnızca eşleşen kurallara sahip yeni etkinlikler başlatıldığında WindowManager kitaplığı tarafından oluşturulur ve bölme kapsayıcısındaki son etkinlik tamamlandığında bölmeler yok edilir.
- Yapılandırma değiştiğinde etkinlikler yeniden başlatılabilir. Bu nedenle, bir bölünme 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ı sürecinden geçebilir. Bu nedenle, uygulama geliştiriciler yaşam döngüsü geri çağırmalarından yeni etkinlikler başlatma gibi konularda dikkatli olmalıdır.
- Cihazlar, etkinlik yerleştirmeyi desteklemek için pencere uzantıları arayüzünü içermelidir. Android 12L (API düzeyi 32) veya sonraki sürümlerin yüklü olduğu büyük ekranlı cihazların neredeyse tamamında arayüz bulunur. Ancak birden fazla etkinliği çalıştırma özelliğine sahip olmayan 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 desteklemeyebilir.
Ek kaynaklar
- Codelab'ler:
- Öğrenme rotası: Etkinlik yerleştirme
- Örnek uygulama: activity-embedding