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, tabletler, katlanabilir cihazlar ve ChromeOS cihazlarda gelişmiş bir kullanıcı deneyimi sunmanıza olanak tanır.
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 ekranlar için destek otomatik olarak sağlanır. Uygulamanız küçük ekranlı bir cihazda olduğunda etkinlikler birbirinin üzerine yığılır. Büyük ekranlarda etkinlikler yan yana gösterilir. 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 (API düzeyi 32) ve sonraki sürümleri çalıştıran büyük ekranlı cihazların çoğunda 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ı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. Uygulamanız, iki etkinliği aynı anda yan yana başlatarak görev penceresini bölebilmektedir:
Görev penceresinin tamamını kaplayan bir etkinlik, yanında yeni bir etkinlik başlatarak da bölme oluşturabilir:
Halihazırda bölünmüş durumda olan ve görev penceresi paylaşan etkinlikler, diğer etkinlikleri aşağıdaki yöntemlerle başlatabilir:
Diğer bir etkinliğin üstünde, yan tarafta:
Önceki birincil etkinliği gizlemek için bölünmüş ekranı yana kaydırın:
Üstte, yani aynı etkinlik yığınında bir etkinlik başlatın:
Aynı görevde bir etkinliğin tam penceresini başlatın:
Geri gezinme
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:
- Birlikte gitme: Etkinlikler birbiriyle ilişkiliyse ve biri diğeri olmadan gösterilmemeliyse geri gezinme, her ikisini de tamamlayacak şekilde yapılandırılabilir.
- Tek başına hareket etme: Etkinlikler tamamen bağımsızsa bir etkinlikte geri gezinme, 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 etkinliği, hareketin gerçekleştiği etkinliğe gönderilir. Kullanıcılar ekranın sol tarafından kaydırdığında geri etkinliği, bölünmüş pencerenin sol bölmesinde bulunan etkinliğe gönderilir. Kullanıcılar ekranın sağ tarafından kaydırdığında geri etkinliği sağdaki bölmede etkinliğe gönderilir.
Android 15 (API düzeyi 35) ve sonraki sürümler
Aynı uygulamadaki 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 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ı bölme işlemi buna örnek verilebilir. 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ı için bu iki etkinlik tek bir etkinlik olarak başlatılır.
Bölünmüş özellikler
Görev penceresinin bölünmüş kapsayıcılar arasında nasıl oranlandığını ve kapsayıcıların birbirine göre nasıl düzenlendiğini belirtebilirsiniz.
XML yapılandırma dosyasında tanımlanan kurallar için aşağıdaki özellikleri ayarlayın:
splitRatio
: Kapsayıcı oranlarını ayarlar. Değer, açık aralıktaki (0,0, 1,0) bir kayan nokta sayısıdır.splitLayoutDirection
: Bölünmüş kapsayıcıların birbirine göre nasıl yerleştirileceğini belirtir. Olası değerlere örnekler:ltr
: Soldan sağartl
: Sağdan solalocale
: Yerel ayardanltr
veyartl
belirlenir
Örnekler için XML yapılandırması bölümüne bakın.
WindowManager API'leri kullanılarak oluşturulan kurallar için SplitAttributes.Builder
ile bir SplitAttributes
nesnesi oluşturun ve aşağıdaki oluşturucu yöntemlerini çağırın:
setSplitType()
: Bölünmüş kapsayıcıların oranlarını ayarlar.SplitAttributes.SplitType.ratio()
yöntemi dahil olmak üzere geçerli bağımsız değişkenler içinSplitAttributes.SplitType
bölümüne bakın.setLayoutDirection()
: Kapsayıcıların düzenini ayarlar. Olası değerler içinSplitAttributes.LayoutDirection
bölümüne bakın.
Örnekler için WindowManager API bölümüne bakın.
Yer tutucular
Yer tutucu etkinlikler, etkinlik bölme alanında yer kaplayan boş ikincil etkinliklerdir. Amaç, bu etkinliklerin içerik barındıran başka bir etkinlikle değiştirilmesidir. Örneğin, bir yer tutucu etkinliği, listeden bir öğe seçilene kadar liste-ayrıntı düzeninde bölünmüş bir etkinliğin ikincil tarafını işgal edebilir. Bu noktada, seçilen liste öğesinin ayrıntı bilgilerini içeren bir etkinlik 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 izin verdiğinde sistem, yer tutucuyu yeniden başlatılmış bir durumda yeniden başlatır.
Ancak SplitPlaceholder.Builder
öğesinin 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 bölmeli ekrandan tek bölmeli ekrana yeniden boyutlandırıldığında yer tutucuyu görev penceresindeki en üst 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 penceresi genişliğini çok bölmeli bir düzen için yeterince büyük olmayacak şekilde azalttığında (örneğin, büyük ekranlı 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ölmesinde yer tutucu olmayan etkinlikler birincil bölmede yer alan etkinliklerin üzerine yığılır.
Yer tutucu etkinlikler yalnızca bölme için yeterli ekran genişliği olduğunda gösterilir. Küçük ekranlarda yer tutucu otomatik olarak kapatılır. Görüntüleme alanı tekrar yeterince büyük olduğunda 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:
Bu işlem sonucunda, aynı görevdeki etkinliklerin z-sıralı düzeni aşağıdaki gibi olur:
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:
Küçük pencerede geriye gittiğinizde, birbirinin üzerine yığılmış etkinlikler arasında gezinebilirsiniz.
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 yan tarafta başlatır ve bölünmüş ekranı yana doğru kaydırır:
Sonuç olarak, aynı görevdeki etkinliklerin aşağıdaki z-sıralı listesi elde edilir:
Daha küçük bir görev penceresinde uygulama, üstte C bulunan tek bir etkinliğe küçülür:
Sabit dikey yön
android:screenOrientation manifest ayarı, uygulamaların etkinlikleri dikey veya yatay yönde kısıtlaması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 veya dikey ekranlarda yatay yönde dikey olarak kırpabilir.
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 bir etkinlik ikinci bir etkinlik başlattığında cihaz, iki etkinliği iki bölmeli ekranda yan yana gösterebilir.
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ölmelerini 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 WindowManager kitaplığına erişmeli ve sistemi, uygulamanın etkinlik yerleştirme özelliğini uyguladığını bilgilendirmelidir.
Aşağıdakileri yapın:
En yeni WindowManager kitaplık bağımlılığını uygulamanızın modül düzeyindeki
build.gradle
dosyasına 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.
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, etkinlik yerleştirmeyi destekleyen uygulamalar için özel özellikleri etkinleştirmek amacıyla bu ayarı kullanır. Ö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 için XML tabanlı bir uygulama oluşturmak üzere aşağıdaki adımları uygulayın:
Aşağıdakileri yapan bir XML kaynak dosyası oluşturun:
- Bölünmüşlüğü 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>
Bir başlatıcı oluşturun.
WindowManager
RuleController
bileşeni, XML yapılandırma dosyasını ayrıştırır ve kuralları sisteme sunar. Jetpack Startup kitaplığıInitializer
, XML dosyasını uygulama başlatılırkenRuleController
'e sunar. Böylece, herhangi bir etkinlik başladığında kurallar geçerli olur.Bir başlatıcı oluşturmak için aşağıdakileri yapın:
Modül düzeyindeki
build.gradle
dosyanıza en yeni Jetpack Startup kitaplık bağımlılığını ekleyin. Örneğin:implementation 'androidx.startup:startup-runtime:1.1.1'
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(); } }
Kural tanımları için bir içerik sağlayıcı oluşturun.
androidx.startup.InitializationProvider
öğesini<provider>
olarak uygulama manifesti dosyanıza ekleyin.RuleController
başlatıcınızın (SplitInitializer
) uygulanmasına dair bir referans ekleyin:<!-- AndroidManifest.xml --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- Make SplitInitializer discoverable by InitializationProvider. --> <meta-data android:name="${applicationId}.SplitInitializer" android:value="androidx.startup" /> </provider>
InitializationProvider
, uygulamanınonCreate()
yöntemi çağrılmadan önceSplitInitializer
'ü bulur ve başlatır. Sonuç 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 olduğundan emin olmak için Application
alt sınıfının onCreate()
yönteminde çağrıları yapın.
Programatik olarak etkinlik bölme oluşturmak için aşağıdakileri yapın:
Bölme kuralı oluşturun:
Bölünmeyi paylaşan etkinlikleri tanımlayan bir
SplitPairFilter
oluşturun:Kotlin
val splitPairFilter = SplitPairFilter( ComponentName(this, ListActivity::class.java), ComponentName(this, DetailActivity::class.java), null )
Java
SplitPairFilter splitPairFilter = new SplitPairFilter( new ComponentName(this, ListActivity.class), new ComponentName(this, DetailActivity.class), null );
Filtreyi bir filtre grubuna ekleyin:
Kotlin
val filterSet = setOf(splitPairFilter)
Java
Set<SplitPairFilter> filterSet = new HashSet<>(); filterSet.add(splitPairFilter);
Bölme için sayfa düzeni özellikleri oluşturun:
Kotlin
val splitAttributes: SplitAttributes = SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build()
Java
final SplitAttributes splitAttributes = new SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build();
SplitAttributes.Builder
, düzen özelliklerini içeren bir nesne oluşturur:setSplitType()
: 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ı.
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
: Bir bölmeyi paylaşan etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen bölme çifti filtreleri içerir.setDefaultSplitAttributes()
: Kural için düzen özelliklerini uygular.setMinWidthDp()
: Bölünmeyi etkinleştiren minimum ekran genişliğini (yoğunluktan bağımsız piksel cinsinden, dp) ayarlar.setMinSmallestWidthDp()
: Cihaz yönüne bakılmaksızın bölme etkinleştirmek için iki ekran boyutundan küçük olanın sahip olması gereken minimum değeri (dp cinsinden) ayarlar.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. AyrıcaSPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
vesetMaxAspectRatioInLandscape()
sayfalarına da göz atın. Yatay için varsayılan değerALWAYS_ALLOW
'dur.setFinishPrimaryWithSecondary()
: İkincil kapsayıcıdaki tüm etkinliklerin tamamlanmasının birincil kapsayıcıdaki etkinlikleri nasıl etkilediğini belirler.NEVER
, ikincil kapsayıcıdaki tüm etkinlikler tamamlandığında sistemin birincil etkinlikleri tamamlamaması gerektiğini belirtir (Etkinlikleri tamamlama bölümüne bakın).setFinishSecondaryWithPrimary()
: Birincil kapsayıcıdaki tüm etkinliklerin tamamlanmasının ikincil kapsayıcıdaki etkinlikleri nasıl etkilediğini belirler.ALWAYS
, birincil kapsayıcıdaki tüm etkinlikler sona erdiğinde sistemin her zaman ikincil kapsayıcıdaki etkinlikleri de bitirmesi gerektiğini belirtir (Etkinlikleri sonlandırma bölümüne bakın).setClearTop()
: Kapsayıcıda yeni bir etkinlik başlatıldığında ikincil kapsayıcıdaki tüm etkinliklerin sona erip ermediğini belirtir.false
değeri, yeni etkinliklerin ikincil kapsayıcıda bulunan etkinliklerin üzerine yığıldığını belirtir.
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);
İçerik mevcut olmadığında ikincil kapsayıcı için bir yer tutucu oluşturun:
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 );
Filtreyi bir filtre grubuna ekleyin:
Kotlin
val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
Java
Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>(); placeholderActivityFilterSet.add(placeholderActivityFilter);
Bir
SplitPlaceholderRule
oluşturun:Kotlin
val splitPlaceholderRule = SplitPlaceholderRule.Builder( placeholderActivityFilterSet, Intent(context, PlaceholderActivity::class.java) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build()
Java
SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder( placeholderActivityFilterSet, new Intent(context, PlaceholderActivity.class) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build();
SplitPlaceholderRule.Builder
kuralı oluşturur ve yapılandırır:placeholderActivityFilterSet
: Yer tutucu etkinliğinin ilişkili olduğu etkinlikleri tanımlayarak kuralın ne zaman uygulanacağını belirleyen etkinlik filtrelerini içerir.Intent
: Yer tutucu etkinliğinin başlatılmasını belirtir.setDefaultSplitAttributes()
: Düzen özelliklerini kurala uygular.setMinWidthDp()
: Bö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, etkinliklerin çoğu tablette görev penceresini dikey yönde doldurmasına neden olur. AyrıcaSPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
vesetMaxAspectRatioInLandscape()
sayfalarına da göz atın. Yatay için varsayılan değerALWAYS_ALLOW
.setFinishPrimaryWithPlaceholder()
: Yer tutucu etkinliğinin tamamlanmasının birincil kapsayıcıdaki etkinlikleri nasıl etkileyeceğini belirler. HER ZAMAN, yer tutucu sona erdiğinde sistemin birincil kapsayıcıdaki etkinlikleri her zaman bitirmesi gerektiğini belirtir (Etkinlikleri sonlandırma bölümüne bakın).setSticky()
: Yer tutucu etkinliğinin, yer tutucu ilk kez yeterli minimum genişliğe sahip bir bölme içinde göründükten sonra küçük ekranlarda etkinlik yığınının üstünde görünüp görünmeyeceğini belirler.
Kuralı WindowManager'a
RuleController
ekleyin:Kotlin
ruleController.addRule(splitPlaceholderRule)
Java
ruleController.addRule(splitPlaceholderRule);
Hiçbir zaman bir bölme işleminin parçası olmaması gereken etkinlikleri belirtin:
Her zaman görev görüntüleme alanının tamamını kaplaması gereken bir etkinliği tanımlayan bir
ActivityFilter
oluşturun:Kotlin
val expandedActivityFilter = ActivityFilter( ComponentName(this, ExpandedActivity::class.java), null )
Java
ActivityFilter expandedActivityFilter = new ActivityFilter( new ComponentName(this, ExpandedActivity.class), null );
Filtreyi bir filtre grubuna ekleyin:
Kotlin
val expandedActivityFilterSet = setOf(expandedActivityFilter)
Java
Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>(); expandedActivityFilterSet.add(expandedActivityFilter);
Bir
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.
Kuralı WindowManager'a
RuleController
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 etkinliği yerleştirme, birden fazla Android uygulamasındaki etkinliklerin görsel olarak entegrasyonunu sağlar. Sistem, tek uygulama etkinliği yerleştirmede olduğu gibi, barındıran uygulamanın etkinliğini ve başka bir uygulamadan yerleştirilmiş etkinliği ekranda yan yana veya üst üste gösterir.
Örneğin, Ayarlar uygulaması, WallpaperPicker uygulamasından duvar kağıdı seçici etkinliğini yerleştirebilir:
Güven modeli
Diğer uygulamalardan etkinlikleri yerleştiren ana makine işlemleri, boyut, konum, kırpma ve şeffaflık dahil olmak üzere yerleştirilen etkinliklerin sunumunu yeniden tanımlayabilir. Kötü amaçlı barındırıcılar, kullanıcıları yanıltmak ve tıklama tuşuyla saldırı veya kullanıcı arayüzünü değiştirmeye yönelik başka saldırılar oluşturmak için bu özelliği kullanabilir.
Android, uygulama içi etkinlik yerleştirmenin kötüye kullanılmasını önlemek için uygulamaların etkinliklerinin yerleştirilmesine izin vermek üzere etkinleştirme yapmasını 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ı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"
... />
Birden fazla sertifika belirtmek için bir dize dizisi de kullanabilirsiniz:
<activity
android:name=".MyEmbeddableActivity"
android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
... />
Aşağıdaki gibi bir kaynağa referans veren:
<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 İmza raporu oluşturma 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 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 ana makine kimliğini doğrulayan özel bir kimlik doğrulama mekanizması oluşturun. Ana makine sertifikalarını biliyorsanız kimlik doğrulama için androidx.security.app.authenticator
kitaplığını kullanın. Düzenleyen, etkinliğinizi yerleştirdikten sonra kimlik doğrulaması yaparsa gerçek içeriği gösterebilirsiniz. Aksi takdirde, kullanıcıya işleme izin verilmediğini bildirebilir ve içeriği engelleyebilirsiniz.
Bir barındırıcının etkinliğinizi yerleştirip yerleştirmediğini kontrol etmek için Jetpack WindowManager kitaplığındaki ActivityEmbeddingController#isActivityEmbedded()
yöntemini kullanın. Örneğin:
Kotlin
fun isActivityEmbedded(activity: Activity): Boolean { return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity) }
Java
boolean isActivityEmbedded(Activity activity) { return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity); }
Minimum boyut kısıtlaması
Android sistemi, uygulama manifest'i <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 sunucusunda güvenliği doğrulayan politika, takma ada değil hedefte ayarlanan işaretlere dayanır.
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ıran 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. Bu nedenle, barındıran uygulamaların hedef etkinliklerin uygulamalar arası yerleştirmeye izin verip vermediğini bilmesi gerekir.
Yerleştirilmiş bir etkinlik aynı görevde yeni bir etkinlik başlatırsa ve yeni etkinlik uygulamalar arası yerleş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ölünmüş örnekler
Tam pencereden bölme
Yeniden yapılandırmaya gerek yoktur. Bölünme yapılandırmasını statik olarak veya çalışma zamanında tanımlayabilir ve ardından ek parametre olmadan Context#startActivity()
işlevini çağırabilirsiniz.
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Varsayılan olarak böl
Bir uygulamanın açılış sayfası, büyük ekranlarda iki kapsayıcıya bölünecek şekilde tasarlandığında, kullanıcı deneyimi en iyi şekilde her iki etkinlik de oluşturulup aynı anda sunulduğunda elde edilir. Ancak kullanıcı birincil kapsayıcıdaki etkinlikle etkileşime geçene kadar içerik, bölünmenin ikincil kapsayıcısı için kullanılamayabilir (örneğin, kullanıcı bir gezinme menüsünden bir öğe seçer). İçerik, bölme işleminin ikincil kapsayıcısında gösterilene kadar yer tutucu etkinlik boşluğu doldurabilir (Yer tutucular bölümüne bakın).
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>
Derin bağlantı bölme
Bir uygulama bir intent aldığında hedef etkinlik, etkinlik bölme işleminin ikincil kısmı olarak gösterilebilir. Örneğin, bir listedeki öğeyle ilgili bilgilerin yer aldığı bir ayrıntı ekranı gösterme isteği. Küçük ekranlarda ayrıntılar tam görev penceresinde, büyük ekranlarda 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, mevcut ekran genişliğine göre doğru sunumu (yığın halinde 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, arka gezinme yığınında kullanıcının kullanabileceği tek etkinlik olabilir. Ayrıntı etkinliğini kapatıp yalnızca ana etkinliği bırakmak isteyebilirsiniz:
Bunun yerine, finishPrimaryWithSecondary
özelliğini kullanarak her iki etkinliği de aynı anda bitirebilirsiniz:
<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 yığmak, kullanıcıların derin içeriğe erişmesine olanak tanır. Ö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:
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ştirilerek gizlenir:
Kullanıcı, 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 varsayılan davranış, etkinliklerin birbirinin üzerine yığılmasıdır. Etkin bir bölme içinde birincil kapsayıcıdan başlatılan etkinlikler de etkinlik yığınının üst kısmındaki ikincil kapsayıcıya gönderilir.
Yeni bir görevdeki etkinlikler
Bölünmüş görev penceresindeki etkinlikler yeni bir görevde etkinlikler başlattığında yeni görev, bölünmeyi içeren görevden ayrıdır ve tam pencerede gösterilir. Son Görevler ekranında iki görev gösterilir: Bölünmüş görev ve yeni görev.
Etkinlik değişimi
Etkinlikler, ikincil kapsayıcı yığınında değiştirilebilir. Örneğin, birincil etkinlik üst düzey gezinme için kullanıldığında ve ikincil etkinlik seçili bir hedef olduğunda. Ü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.
Uygulama, gezinme seçimi değiştiğinde 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, birincil bölmede bir menünüz ve ikincil bölmede A ve B ekranları yığılmışsa kullanıcı telefonu katladığında B, A'nın üstüne, A da menünün üstüne gelir. 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 yerleştirip eski kapsayıcıları arka yığınta tutmaktır. Bölümleri, önceki ikincil kapsayıcıları clearTop
ile temizleyecek ve yeni etkinlikleri normal şekilde başlatacak şekilde yapılandırabilirsiniz.
<SplitPairRule
window:clearTop="true">
<SplitPairFilter
window:primaryActivityName=".Menu"
window:secondaryActivityName=".ScreenA"/>
<SplitPairFilter
window:primaryActivityName=".Menu"
window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>
Kotlin
class MenuActivity { . . . fun onMenuItemSelected(selectedMenuItem: Int) { startActivity(Intent(this, classForItem(selectedMenuItem))) } }
Java
public class MenuActivity { . . . void onMenuItemSelected(int selectedMenuItem) { startActivity(new Intent(this, classForItem(selectedMenuItem))); } }
Alternatif olarak, aynı ikincil etkinliği kullanın ve birincil (menü) etkinlikten aynı örneği çözen ancak ikincil kapsayıcıda bir durum veya kullanıcı arayüzü güncellemesi tetikleyen yeni intent'ler gönderin.
Birden fazla bölme
Uygulamalar, yan tarafta ek etkinlikler başlatarak çok düzeyli derin gezinme sağlayabilir.
İkincil kapsayıcıdaki bir etkinlik yan tarafta yeni bir etkinlik başlattığında, mevcut bölme üzerine yeni bir bölme oluşturulur.
Arka yığın, daha önce açılmış tüm etkinlikleri içerir. Böylece kullanıcılar C'yi tamamladıktan sonra A/B bölmelerine gidebilir.
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ını belirtin ve C etkinliğini normal ş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ölme durumu değişikliklerine tepki verme
Bir uygulamadaki farklı etkinliklerde aynı işlevi gerçekleştiren kullanıcı arayüzü öğeleri olabilir. Örneğin, hesap ayarlarını içeren bir pencere açan bir kontrol.
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.
Etkinliklerin ne zaman bölündüğünü öğrenmek için SplitController.splitInfoList
akışını kontrol edin veya bölünmüş durumdaki değişiklikler için SplitControllerCallbackAdapter
ile bir dinleyici kaydedin. Ardından kullanıcı arayüzünü uygun şekilde ayarlayın:
Kotlin
val layout = layoutInflater.inflate(R.layout.activity_main, null) val view = layout.findViewById<View>(R.id.infoButton) lifecycleScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance. .collect { list -> view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE } } }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { . . . new SplitControllerCallbackAdapter(SplitController.getInstance(this)) .addSplitListener( this, Runnable::run, splitInfoList -> { View layout = getLayoutInflater().inflate(R.layout.activity_main, null); layout.findViewById(R.id.infoButton).setVisibility( splitInfoList.isEmpty() ? View.VISIBLE : View.GONE); }); }
İş 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 Yaşam döngüsü bilincine sahip bileşenlerle Kotlin iş parçacıklarını 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()
'te kayıtlı, onStop()
'te ise kayıtsız olmalıdır.
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. Modüler etkinliklerin bölünmüş ekranda görünmesi engellenmelidir.
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 tamamlama
Kullanıcılar, ekranın kenarından kaydırarak bölünmüş ekranın her iki tarafındaki etkinlikleri bitirebilir:
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ünmenin bir tarafındaki tüm etkinliklerin tamamlanmasının, bölünmenin diğer tarafındaki etkinlikleri nasıl etkilediğini yapılandırmak için bölme çifti kural özelliklerini belirtebilirsiniz. Özellikler şunlardır:
window:finishPrimaryWithSecondary
: İkincil kapsayıcıdaki tüm etkinliklerin tamamlanması birincil kapsayıcıdaki etkinlikleri nasıl etkiler?window:finishSecondaryWithPrimary
: Birincil kapsayıcıdaki tüm etkinliklerin tamamlanması, ikincil kapsayıcıdaki etkinlikleri nasıl etkiler?
Özelliklerin olası değerleri şunlardır:
always
: Etkinlikleri her zaman ilişkili kapsayıcıda tamamlayınnever
: İlişkili kapsayıcıdaki etkinlikler hiçbir zaman tamamlanmaz.adjacent
: İki kapsayıcı yan yana gösterildiğinde ilişkili kapsayıcıdaki etkinlikleri sonlandırın ancak iki kapsayıcı yığıldığında sonlandırmayın.
Örnek:
<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 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>
Etkinlikleri birlikte tamamlama
İkincil kapsayıcıdaki tüm etkinlikler sona erdiğinde birincil kapsayıcıdaki etkinlikleri otomatik olarak sonlandırın:
<SplitPairRule
window:finishPrimaryWithSecondary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
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>
Birincil veya ikincil kapsayıcıdaki tüm etkinlikler tamamlandığında etkinlikleri birlikte sonlandırın:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Kapsayıcılarda birden fazla etkinliği tamamlama
Bölünmüş bir kapsayıcıda birden fazla etkinlik yığılmışsa yığının en altındaki bir etkinliğin sonlandırılması, en üstteki etkinliklerin otomatik olarak sonlandırılmasını sağlamaz.
Örneğin, ikincil kapsayıcıda iki etkinlik varsa B'nin üzerinde C:
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>
Üstteki etkinliği bitirdiğinizde bölme korunur.
İkincil kapsayıcının alt (kök) etkinliği sonlandırılırsa üstteki etkinlikler kaldırılmaz ve bölme korunur.
Etkinlikleri birlikte tamamlamayla ilgili ek kurallar (ör. ikincil etkinliği birincil etkinlikle tamamlama) da uygulanır:
<SplitPairRule
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Bölme, birincil ve ikincil kampanyayı birlikte bitirmek üzere yapılandırıldığında:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
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ının değiştirilmesi, ek etkinlik lansmanlarını ve yeni kapsayıcıları etkiler ancak mevcut ve etkin bölme noktalarını etkilemez.
Etkin bölmelerin özelliklerini değiştirmek için bölmedeki yan etkinliği veya etkinlikleri tamamlayın ve yeni bir yapılandırmayla yan tarafta tekrar başlatın.
Dinamik bölünmüş mülkler
Jetpack WindowManager 1.4 ve sonraki sürümler tarafından desteklenen Android 15 (API düzeyi 35) ve sonraki sürümler, etkinlik yerleştirme bölmelerinin yapılandırılabilirliğini sağlayan dinamik özellikler sunar. Örneğin:
- Bölme genişletme: Etkileşimli ve sürüklenebilir bir bölme, kullanıcıların bölünmüş bir sunumdaki bölmelerin boyutunu değiştirmesini sağlar.
- Etkinlik grubunu 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.
- İletişim kutusunun tam ekranda karartılması: Uygulamalar, 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ölmeyi genişletme
Panel genişletme, kullanıcıların çift panel düzenindeki iki etkinliğe ayrılan ekran alanı miktarını ayarlamalarına olanak tanır.
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:
DividerAttributes
örneği oluşturmaBölme özelliklerini özelleştirin:
color
: Taşınabilir bölme ayırıcının rengi.widthDp
: Taşınabilir bölme ayırıcının genişliği. Bölücünün genişliğini sistemin belirlemesine izin vermek içinWIDTH_SYSTEM_DEFAULT
olarak ayarlayın.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 yığınını sabitleme
Etkinlik grubu 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 grubu sabitleme, gelişmiş bir çoklu görev deneyimi sunar.
Uygulamanızda etkinlik grubu sabitlemeyi etkinleştirmek için aşağıdakileri yapın:
Sabitlemek istediğiniz etkinliğin (ör. liste-ayrıntı düzeninin ayrıntı etkinliği) düzen dosyasına bir düğme ekleyin:
<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üğme için bir onclick dinleyicisi ayarlayın: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); });
İletişim kutusu tam ekran loş
Etkinlikler genellikle bir iletişim kutusuna dikkat ç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 iletişim kutusu açıldığında uygulama penceresinin tamamı varsayılan olarak 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
simgesini kullanın.
Bölünmüş pencereden tam ekrana etkinlik ayıklama
Yan etkinliği tam pencerede gösteren yeni bir yapılandırma oluşturun ve ardından etkinliği aynı örneği çözen bir intent ile 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ölünmeler desteklenmiyorsa etkinlikler, etkinlik yığınının üstünde başlatılır (etkinlik dışı yerleştirme modeline göre).
Sistem geçersiz kılınmasını önleme
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, uygulamada herhangi bir değişiklik yapmadan liste-ayrıntı gibi çok bölmeli düzenler aracılığıyla uygulama sunumunu iyileştirebilir. Ancak sistemin etkinlik yerleştirmesi, yanlış uygulama düzenleri, hatalar veya uygulama tarafından uygulanan etkinlik yerleştirmeyle çakışmalara da neden olabilir.
Uygulamanız, uygulama manifest dosyasında bir mülk ayarlayarak sistem etkinliğinin yerleştirilmesini önleyebilir 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>
Mülk adı, Jetpack WindowManager WindowProperties
nesnesinde tanımlanır. Uygulamanız etkinlik yerleştirme özelliğini uyguluyorsa veya sistemin etkinlik yerleştirme kurallarını uygulamanıza uygulamasını başka bir şekilde engellemek istiyorsanız değeri false
olarak ayarlayın. Sistemin, sistem tanımlı etkinlik yerleştirme özelliğini 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 etkinliğinin sahibi olarak tanımlanan, görevin ana uygulaması diğer etkinlikleri düzenleyip 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. Yeni bir görevde başlatılan etkinlikler her zaman mevcut bölmelerin dışında yeni ve genişletilmiş bir pencerede açılır.
- Yalnızca aynı süreçteki etkinlikler düzenlenebilir ve bölünebilir. Farklı işlemlerdeki etkinlikler hakkında bilgi edinmenin bir yolu olmadığından
SplitInfo
geri çağırma işlevi yalnızca aynı işleme ait etkinlikleri bildirir. - Her çift veya tek etkinlik kuralı yalnızca kuralın kaydedilmesinden sonra gerçekleşen etkinlik lansmanları için geçerlidir. Mevcut bölmelerin veya görsel özelliklerinin güncellenmesi şu anda mümkün değildir.
- Bölünmüş çift filtre yapılandırması, etkinlikler tamamen başlatılırken kullanılan intent'lerle eşleşmelidir. Eşleme, uygulama sürecinden yeni bir etkinliğin başlatıldığı noktada gerçekleşir. Bu nedenle, gizli intent'ler kullanıldığında sistem sürecinde daha sonra çözülen bileşen adlarını bilemez. Bir bileşen adı lansman sırasında bilinmiyorsa bunun yerine joker karakter ("*/*") kullanılabilir ve filtreleme, intent işlemine göre yapılabilir.
- Ş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ölünmeler yalnızca WindowManager kitaplığı tarafından, eşleşen kurallara sahip yeni etkinlikler başlatıldığında oluşturulur ve bölünmüş kapsayıcıdaki son etkinlik sona erdiğinde bölünmeler yok edilir.
- Yapılandırma değiştiğinde etkinlikler yeniden başlatılabilir. Bu nedenle, bir bölme oluşturulduğunda veya kaldırıldığında ve etkinlik sınırları değiştiğinde etkinlik, önceki örneğin tamamen yok edilmesi ve yenisinin oluşturulması işlemini gerçekleştirebilir. 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ümleri çalıştıran neredeyse tüm büyük ekranlı cihazlarda bu arayüz bulunur. Ancak birden fazla etkinlik çalıştıramayan bazı büyük ekranlı cihazlarda pencere uzantıları arayüzü bulunmaz. Büyük ekranlı cihazlar çoklu pencere modunu desteklemiyorsa etkinlik yerleştirmeyi de desteklemeyebilir.
Ek kaynaklar
- Codelab'ler:
- Öğrenme rotası: Etkinlik yerleştirme
- Örnek uygulama: activity-embedding