Büyük ve katlanmamış ekranlar ile benzersiz katlanmış durumlar, katlanabilir cihazlarda yeni kullanıcı deneyimlerine olanak tanır. Uygulamanızı katlanabilir cihazlara uygun hale getirmek için Jetpack WindowManager kitaplığını kullanın. Bu kitaplık, katlanabilir cihazların pencere özellikleriyle (ör. katlanma ve menteşe) ilgili bir API yüzeyi sağlar. Uygulamanız katlama özelliğini desteklediğinde, önemli içerikleri katlama veya menteşe alanına yerleştirmemek için düzenini uyarlayabilir ve katlama ile menteşeleri doğal ayırıcılar olarak kullanabilir.
Bir cihazın masaüstü veya kitap duruşu gibi yapılandırmaları destekleyip desteklemediğini anlamak, farklı düzenleri destekleme veya belirli özellikler sunma konusundaki kararlara yön verebilir.
Pencere bilgileri
Jetpack WindowManager'daki WindowInfoTracker
arayüzü, pencere düzeni bilgilerini gösterir. Arayüzün windowLayoutInfo()
yöntemi, uygulamanızı katlanabilir bir cihazın katlanma durumu hakkında bilgilendiren WindowLayoutInfo
verileri akışını döndürür. WindowInfoTracker#getOrCreate()
yöntemi, WindowInfoTracker
öğesinin bir örneğini oluşturur.
WindowManager, Kotlin akışları ve Java geri çağırmaları kullanılarak WindowLayoutInfo
veri toplanmasını destekler.
Kotlin akışları
WindowLayoutInfo
veri toplamayı başlatmak ve durdurmak için repeatOnLifecycle
kod bloğunun yaşam döngüsü en az STARTED
olduğunda yürütüldüğü ve yaşam döngüsü STOPPED
olduğunda durdurulduğu yeniden başlatılabilir yaşam döngüsü farkında olan bir eşzamanlı rutin kullanabilirsiniz. Yaşam döngüsü STARTED
olduğunda kod bloğunun yürütülmesi otomatik olarak yeniden başlatılır. Aşağıdaki örnekte, kod bloğu WindowLayoutInfo
verilerini toplar ve kullanır:
class DisplayFeaturesActivity : AppCompatActivity() {
private lateinit var binding: ActivityDisplayFeaturesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDisplayFeaturesBinding.inflate(layoutInflater)
setContentView(binding.root)
lifecycleScope.launch(Dispatchers.Main) {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
WindowInfoTracker.getOrCreate(this@DisplayFeaturesActivity)
.windowLayoutInfo(this@DisplayFeaturesActivity)
.collect { newLayoutInfo ->
// Use newLayoutInfo to update the layout.
}
}
}
}
}
Java geri çağırmaları
androidx.window:window-java
bağımlılığında bulunan geri çağırma uyumluluk katmanı, Kotlin akışı kullanmadan WindowLayoutInfo
güncellemelerini toplamanıza olanak tanır. Yapı, WindowInfoTrackerCallbackAdapter
sınıfını içerir. Bu sınıf, WindowInfoTracker
öğesini uyarlayarak örneğin WindowLayoutInfo
güncellemelerini almak için geri çağırmaları kaydetmeyi (ve kaydı silmeyi) destekler:
public class SplitLayoutActivity extends AppCompatActivity {
private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private ActivitySplitLayoutBinding binding;
private final LayoutStateChangeCallback layoutStateChangeCallback =
new LayoutStateChangeCallback();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
windowInfoTracker =
new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}
@Override
protected void onStart() {
super.onStart();
windowInfoTracker.addWindowLayoutInfoListener(
this, Runnable::run, layoutStateChangeCallback);
}
@Override
protected void onStop() {
super.onStop();
windowInfoTracker
.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}
class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
@Override
public void accept(WindowLayoutInfo newLayoutInfo) {
SplitLayoutActivity.this.runOnUiThread( () -> {
// Use newLayoutInfo to update the layout.
});
}
}
}
RxJava desteği
RxJava'yı (2
veya 3
sürümü) kullanıyorsanız Kotlin akışı kullanmadan WindowLayoutInfo
güncellemelerini toplamanıza olanak tanıyan Observable
veya Flowable
kullanmanızı sağlayan yapılardan yararlanabilirsiniz.
androidx.window:window-rxjava2
ve androidx.window:window-rxjava3
bağımlılıkları tarafından sağlanan uyumluluk katmanı, uygulamanızın WindowLayoutInfo
güncellemelerini almasını sağlayan WindowInfoTracker#windowLayoutInfoFlowable()
ve WindowInfoTracker#windowLayoutInfoObservable()
yöntemlerini içerir. Örneğin:
class RxActivity: AppCompatActivity {
private lateinit var binding: ActivityRxBinding
private var disposable: Disposable? = null
private lateinit var observable: Observable<WindowLayoutInfo>
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Create a new observable.
observable = WindowInfoTracker.getOrCreate(this@RxActivity)
.windowLayoutInfoObservable(this@RxActivity)
}
@Override
protected void onStart() {
super.onStart();
// Subscribe to receive WindowLayoutInfo updates.
disposable?.dispose()
disposable = observable
.observeOn(AndroidSchedulers.mainThread())
.subscribe { newLayoutInfo ->
// Use newLayoutInfo to update the layout.
}
}
@Override
protected void onStop() {
super.onStop();
// Dispose of the WindowLayoutInfo observable.
disposable?.dispose()
}
}
Katlanabilir ekranların özellikleri
Jetpack WindowManager'ın WindowLayoutInfo
sınıfı, bir ekran penceresinin özelliklerini DisplayFeature
öğeleri listesi olarak kullanılabilir hâle getirir.
FoldingFeature
, aşağıdaki özellikleri de içeren katlanabilir ekranlar hakkında bilgi sağlayan bir DisplayFeature
türüdür:
state
: Cihazın katlanmış durumu,FLAT
veyaHALF_OPENED
orientation
: Katlama veya menteşenin yönü,HORIZONTAL
veyaVERTICAL
occlusionType
: Katlama veya menteşe, ekranın bir kısmını gizliyor mu?NONE
veyaFULL
isSeparating
: Katlama veya menteşe, iki mantıksal ekran alanı oluşturuyor mu? Doğru veya yanlış.
Ekran iki görüntüleme alanına ayrıldığından katlanabilir cihazlar HALF_OPENED
her zaman isSeparating
olarak bildirir. Ayrıca, uygulama her iki ekrana da yayıldığında çift ekranlı bir cihazda isSeparating
her zaman doğrudur.
FoldingFeature
bounds
özelliği (DisplayFeature
öğesinden devralınır), katlama veya menteşe gibi katlanabilir bir özelliğin sınırlayıcı dikdörtgenini temsil eder.
Sınırlar, ekrandaki öğeleri özelliğe göre konumlandırmak için kullanılabilir:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
// ...
lifecycleScope.launch(Dispatchers.Main) {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
// Safely collects from WindowInfoTracker when the lifecycle is
// STARTED and stops collection when the lifecycle is STOPPED.
WindowInfoTracker.getOrCreate(this@MainActivity)
.windowLayoutInfo(this@MainActivity)
.collect { layoutInfo ->
// New posture information.
val foldingFeature = layoutInfo.displayFeatures
.filterIsInstance<FoldingFeature>()
.firstOrNull()
// Use information from the foldingFeature object.
}
}
}
}
Java
private WindowInfoTrackerCallbackAdapter windowInfoTracker;
private final LayoutStateChangeCallback layoutStateChangeCallback =
new LayoutStateChangeCallback();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// ...
windowInfoTracker =
new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(this));
}
@Override
protected void onStart() {
super.onStart();
windowInfoTracker.addWindowLayoutInfoListener(
this, Runnable::run, layoutStateChangeCallback);
}
@Override
protected void onStop() {
super.onStop();
windowInfoTracker.removeWindowLayoutInfoListener(layoutStateChangeCallback);
}
class LayoutStateChangeCallback implements Consumer<WindowLayoutInfo> {
@Override
public void accept(WindowLayoutInfo newLayoutInfo) {
// Use newLayoutInfo to update the Layout.
List<DisplayFeature> displayFeatures = newLayoutInfo.getDisplayFeatures();
for (DisplayFeature feature : displayFeatures) {
if (feature instanceof FoldingFeature) {
// Use information from the feature object.
}
}
}
}
Masa üstü duruşu
Uygulamanız, FoldingFeature
nesnesinde yer alan bilgileri kullanarak telefonu bir yüzeye yerleştirme, menteşeyi yatay konuma getirme ve katlanabilir ekranı yarıya kadar açma gibi duruşları destekleyebilir.
Masaüstü duruşu, kullanıcıların telefonlarını ellerinde tutmadan kullanabilmelerini sağlar. Masa üstü duruşu, medya izlemek, fotoğraf çekmek ve görüntülü görüşme yapmak için idealdir.

Cihazın masaüstü duruşunda olup olmadığını belirlemek için FoldingFeature.State
ve FoldingFeature.Orientation
kullanın:
Kotlin
fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean {
contract { returns(true) implies (foldFeature != null) }
return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
}
Java
boolean isTableTopPosture(FoldingFeature foldFeature) {
return (foldFeature != null) &&
(foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
(foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL);
}
Cihazın masaüstü duruşunda olduğunu öğrendikten sonra uygulama düzeninizi buna göre güncelleyin. Medya uygulamalarında bu genellikle oynatmanın katlanma çizgisinin üzerinde yerleştirilmesi ve kontroller ile ek içeriklerin, eller serbest görüntüleme veya dinleme deneyimi için hemen ardından konumlandırılması anlamına gelir.
Android 15 (API düzeyi 35) ve sonraki sürümlerde, cihazın mevcut durumundan bağımsız olarak bir cihazın masaüstü duruşunu destekleyip desteklemediğini tespit etmek için senkron bir API çağırabilirsiniz.
API, cihaz tarafından desteklenen duruşların bir listesini sağlar. Liste, masaüstü duruşunu içeriyorsa duruşu desteklemek için uygulama düzeninizi bölebilir ve masaüstü ile tam ekran düzenleri için uygulama kullanıcı arayüzünüzde A/B testleri çalıştırabilirsiniz.
Kotlin
if (WindowSdkExtensions.getInstance().extensionsVersion >= 6) {
val postures = WindowInfoTracker.getOrCreate(context).supportedPostures
if (postures.contains(TABLE_TOP)) {
// Device supports tabletop posture.
}
}
Java
if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
List<SupportedPosture> postures = WindowInfoTracker.getOrCreate(context).getSupportedPostures();
if (postures.contains(SupportedPosture.TABLETOP)) {
// Device supports tabletop posture.
}
}
Örnekler
MediaPlayerActivity
uygulaması: Katlanabilir cihazlara uygun bir video oynatıcı oluşturmak için Media3 Exoplayer ve WindowManager'ı nasıl kullanacağınızı öğrenin.Jetpack WindowManager ile katlanabilir cihazlarda kamera uygulamanızı optimize etme codelab: Fotoğrafçılık uygulamaları için masaüstü duruşunu nasıl uygulayacağınızı öğrenin. Vizörü ekranın üst yarısında (katlama çizgisinin üstünde), kontrolleri ise alt yarısında (katlama çizgisinin altında) gösterin.
Kitap duruşu
Kitap duruşu da benzersiz bir katlanabilir özellik. Bu duruşta cihaz yarıya kadar açılıyor ve menteşe dikey konumda oluyor. Kitap duruşu, e-kitap okumak için idealdir. Büyük ekranlı katlanabilir cihazlarda, ciltli kitap gibi açılan iki sayfalık düzenle kitap duruşu, gerçek kitap okuma deneyimini yakalar.
Ellerinizi kullanmadan fotoğraf çekerken farklı bir en boy oranı yakalamak istiyorsanız fotoğrafçılık için de kullanılabilir.
Kitap duruşunu, masaüstü duruşu için kullanılan tekniklerle aynı şekilde uygulayın. Tek fark, kodun katlama özelliği yönünün yatay yerine dikey olduğunu kontrol etmesi gerektiğidir:
Kotlin
fun isBookPosture(foldFeature : FoldingFeature?) : Boolean {
contract { returns(true) implies (foldFeature != null) }
return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
foldFeature.orientation == FoldingFeature.Orientation.VERTICAL
}
Java
boolean isBookPosture(FoldingFeature foldFeature) {
return (foldFeature != null) &&
(foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
(foldFeature.getOrientation() == FoldingFeature.Orientation.VERTICAL);
}
Pencere boyutu değişiklikleri
Bir cihazın yapılandırmasında değişiklik yapıldığında (ör. cihaz katlandığında veya açıldığında, döndürüldüğünde ya da çoklu pencere modunda bir pencerenin boyutu değiştirildiğinde) uygulamanın görüntüleme alanı değişebilir.
Jetpack WindowManager WindowMetricsCalculator
sınıfı, mevcut ve maksimum pencere metriklerini almanızı sağlar. API düzeyi 30'da kullanıma sunulan platform gibi, WindowMetrics
WindowManager
WindowMetrics
de pencere sınırlarını sağlar ancak API, API düzeyi 14'e kadar geriye dönük olarak uyumludur.
Pencere boyutu sınıflarını kullanma başlıklı makaleyi inceleyin.
Ek kaynaklar
Örnekler
- Jetpack WindowManager: Jetpack WindowManager kitaplığının nasıl kullanılacağına dair örnek
- Jetcaster : Compose ile masaüstü duruşu uygulama
Codelab uygulamaları
- Jetpack WindowManager ile katlanabilir ve çift ekranlı cihazları destekleme
- Jetpack WindowManager ile katlanabilir cihazlarda kamera uygulamanızı optimize etme