Katlanmış durumdayken büyük ekranlar ve benzersiz katlanmış durumlar, katlanabilir cihazlarda yeni kullanıcı deneyimleri sağlar. Uygulamanızı katlanabilir cihazlara uygun hale getirmek için katlar ve menteşeler gibi katlanabilir cihaz penceresi özellikleri için API yüzeyi sağlayan Jetpack WindowManager kitaplığını kullanın. Uygulamanız katlanabilir cihazlara uyumlu olduğunda, ö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 ile ilgili kararlara rehberlik edebilir.
Pencere bilgileri
Jetpack WindowManager'daki WindowInfoTracker
arayüzü, pencere düzeni bilgilerini gösterir. Arayüzün windowLayoutInfo()
yöntemi, uygulamanızı katlanabilir cihazın katlanma durumu hakkında bilgilendiren bir WindowLayoutInfo
veri akışı döndürür. WindowInfoTracker#getOrCreate()
yöntemi, WindowInfoTracker
örneği oluşturur.
WindowManager, Kotlin akışları ve Java geri çağırma işlevlerini kullanarak WindowLayoutInfo
verilerini toplama desteği sağlar.
Kotlin akışları
WindowLayoutInfo
veri toplamayı başlatmak ve durdurmak için, yaşam döngüsü en az STARTED
olduğunda repeatOnLifecycle
kod bloğunun yürütüldüğü ve yaşam döngüsü STOPPED
olduğunda durdurulduğu bir yeniden başlatılabilir yaşam döngüsü bilinçli işleyici kullanabilirsiniz. Yaşam döngüsü tekrar 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 toplayıp 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ığına dahil edilen geri çağırma uyumluluk katmanı, Kotlin akışı kullanmadan WindowLayoutInfo
güncellemelerini toplamanıza olanak tanır. Yapı, WindowLayoutInfo
güncellemelerini almak için geri çağırmaları kaydetmek (ve kayıtlarını iptal etmek) desteklemek üzere bir WindowInfoTracker
uyarlayan WindowInfoTrackerCallbackAdapter
sınıfını içerir. Örneğin:
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
(2
veya 3
sürümü) kullanıyorsanız Kotlin akışı kullanmadan WindowLayoutInfo
güncellemelerini toplamak için Observable
veya Flowable
kullanmanıza olanak tanıyan 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üncellemeleri 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ı, görüntüleme penceresinin özelliklerini DisplayFeature
öğelerinin listesi olarak sunar.
FoldingFeature
, aşağıdakiler de dahil olmak üzere katlanabilir ekranlarla ilgili 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
: Kıvrımın veya menteşenin ekranın bir kısmını gizleyip kapatmayacağı,NONE
veyaFULL
isSeparating
: Katlama veya menteşenin iki mantıksal görüntüleme alanı oluşturup oluşturmayacağı (doğru veya yanlış)
HALF_OPENED
olan katlanabilir cihazlar, ekran iki ekran alanına ayrıldığı için isSeparating
değerini her zaman doğru olarak bildirir. Ayrıca, uygulama her iki ekranı da kapladığında isSeparating
çift ekranlı cihazlarda her zaman doğru olur.
FoldingFeature
bounds
özelliği (DisplayFeature
kaynağından devralınır), katlama veya menteşe gibi katlama özelliğinin 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
FoldingFeature
nesnesine dahil edilen bilgileri kullanarak uygulamanız, telefonun bir yüzeye yerleştirildiği, menteşenin yatay konumda olduğu ve katlanabilir ekranın yarı açık olduğu masaüstü gibi duruşları destekleyebilir.
Masaüstü duruşu, kullanıcılara telefonlarını ellerinde tutmadan kullanma kolaylığı sunar. 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ü modunda olup olmadığını belirlemek için FoldingFeature.State
ve FoldingFeature.Orientation
parametrelerini 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ü modunda olduğunu öğrendikten sonra uygulama düzeninizi buna göre güncelleyin. Medya uygulamaları için bu, genellikle oynatma düğmesini ekranın üst kısmına yerleştirmek ve eller serbest izleme veya dinleme deneyimi için kontrolleri ve ek içeriği hemen altına yerleştirmek anlamına gelir.
Android 15 (API seviyesi 35) ve sonraki sürümlerde, cihazın mevcut durumundan bağımsız olarak bir cihazın masaüstü modunu destekleyip desteklemediğini algılamak için senkron API çağırabilirsiniz.
API, cihaz tarafından desteklenen duruşların listesini sağlar. Listede masa üstü duruşu varsa uygulama düzeninizi duruşu destekleyecek şekilde bölebilir, masaüstü ve tam ekran düzenler için uygulamanızın kullanıcı arayüzünde 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 Media3Exoplayer ve WindowManager'ı nasıl kullanacağınızı öğrenin.Jetpack WindowManager ile katlanabilir cihazlarda kamera uygulamanızı optimize edin codelab: Fotoğraf uygulamaları için masaüstü modunu nasıl uygulayacağınızı öğrenin. Vizörü ekranın üst yarısında (katlamanın üstünde), kontrolleri ise alt yarısında (katlamanın altında) gösterin.
Kitap duruşu
Bir başka benzersiz katlanabilir özellik ise cihazın yarı açık, menteşesinin dikey olduğu kitap duruşudur. Kitap okuma duruşu, e-kitap okumak için idealdir. Katlanabilir büyük ekranda ciltli bir kitap gibi açılan iki sayfalık bir düzene sahip kitap modu, gerçek bir kitap okuma deneyimini yakalar.
Ellerinizi kullanmadan fotoğraf çekerken farklı bir en boy oranı kullanmak isterseniz de bu özelliği kullanabilirsiniz.
Kitap duruşunu, masaüstü duruşunda kullanılan tekniklerle uygulayın. Tek fark, kodun katlama özelliğinin yönü için yatay yerine dikey değeri kontrol etmesidir:
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 uygulamanın görüntüleme alanı, cihaz yapılandırmasında yapılan bir değişiklik sonucunda değişebilir. Örneğin, cihaz katlandığında veya açıldığında, döndürüldüğünde ya da çoklu pencere modunda bir pencerenin boyutu değiştirildiğinde.
Jetpack WindowManager WindowMetricsCalculator
sınıfı, mevcut ve maksimum pencere metriklerini almanıza olanak tanır. API düzeyi 30'da kullanıma sunulan platform WindowMetrics
gibi WindowManager
WindowMetrics
da pencere sınırlarını sağlar ancak API, API düzeyi 14'e kadar geriye dönük 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ğını gösteren örnek
- Jetcaster : Compose ile masaüstü duruşu uygulaması
Codelab uygulamaları
- Jetpack WindowManager ile katlanabilir ve çift ekranlı cihazları destekleme
- Jetpack WindowManager ile katlanabilir cihazlarda kamera uygulamanızı optimize etme